Merge remote-tracking branch 'origin/GP-2085_ryanmkurtz_Swift-Metadata--SQUASHED'

This commit is contained in:
Ryan Kurtz
2023-06-12 13:07:03 -04:00
23 changed files with 2654 additions and 0 deletions
@@ -0,0 +1,57 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.analysis;
import java.io.IOException;
import ghidra.app.services.*;
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.Program;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
public class SwiftTypeMetadataAnalyzer extends AbstractAnalyzer {
private static final String NAME = "Swift Type Metadata Analyzer";
private static final String DESCRIPTION = "Discovers Swift type metadata records.";
public SwiftTypeMetadataAnalyzer() {
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
setDefaultEnablement(true);
setPriority(AnalysisPriority.FORMAT_ANALYSIS);
}
@Override
public boolean canAnalyze(Program program) {
return SwiftUtils.isSwift(program);
}
@Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws CancelledException {
try {
SwiftTypeMetadata typeMetadata = new SwiftTypeMetadata(program, monitor, log);
typeMetadata.markup();
}
catch (IOException e) {
return false;
}
return true;
}
}
@@ -0,0 +1,60 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift;
import java.util.List;
/**
* Used to refer to a Swift section, which can have different names depending on the platform
*
* @see <a href="https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/Swift.def">llvm/BinaryFormat/Swift.def</a>
*/
public enum SwiftSection {
BLOCK_FIELDMD("__swift5_fieldmd", "swift5_fieldmd", ".sw5flmd"),
BLOCK_ASSOCTY("__swift5_assocty", "swift5_assocty", ".sw5asty"),
BLOCK_BUILTIN("__swift5_builtin", "swift5_builtin", ".sw5bltn"),
BLOCK_CAPTURE("__swift5_capture", "swift5_capture", ".sw5cptr"),
BLOCK_TYPEREF("__swift5_typeref", "swift5_typeref", ".sw5tyrf"),
BLOCK_REFLSTR("__swift5_reflstr", "swift5_reflstr", ".sw5rfst"),
BLOCK_CONFORM("__swift5_proto", "swift5_protocol_conformances", ".sw5prtc"),
BLOCK_PROTOCS("__swift5_protos", "swift5_protocols", ".sw5prt"),
BLOCK_ACFUNCS("__swift5_acfuncs", "swift5_accessible_functions", ".sw5acfn"),
BLOCK_MPENUM("__swift5_mpenum", "swift5_mpenum", ".sw5mpen"),
BLOCK_TYPES("__swift5_types", "swift5_types", ".sw5tymd"),
BLOCK_ENTRY("__swift5_entry", "swift5_entry", ".sw5entr");
private List<String> sectionNames;
/**
* Create a new {@link SwiftSection}
*
* @param names The names the section goes by
*/
private SwiftSection(String... names) {
sectionNames = List.of(names);
}
/**
* Gets a {@link List} of the {@link SwiftSection}'s names
*
* @return A {@link List} of the {@link SwiftSection}'s names
*/
public List<String> getSwiftSectionNames() {
return sectionNames;
}
}
@@ -0,0 +1,40 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift;
import ghidra.app.util.bin.StructConverter;
/**
* Implemented by all Swift structures
*/
public interface SwiftStructure extends StructConverter {
public static final String DATA_TYPE_CATEGORY = "/Swift";
/**
* Gets the name of the {@link SwiftStructure}
*
* @return The name of the {@link SwiftStructure}
*/
public String getStructureName();
/**
* Gets a short description of the {@link SwiftStructure}
*
* @return A short description of the {@link SwiftStructure}
*/
public String getDescription();
}
@@ -0,0 +1,94 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryBlock;
/**
* Swift-related utility methods
*/
public class SwiftUtils {
/**
* A {@link PointerTypedef pointer} to a relative 4-byte offset
*/
public static final PointerTypedef PTR_RELATIVE =
new PointerTypedef(null, null, 4, null, PointerType.RELATIVE);
/**
* A {@link PointerTypedef string pointer} to a 4-byte relative offset
*/
public static final PointerTypedef PTR_STRING =
new PointerTypedef(null, StringDataType.dataType, 4, null, PointerType.RELATIVE);
/**
* Checks if the given {@link Program} is a Swift program
*
* @param program The {@link Program} to check
* @return True if the given {@link Program} is a Swift program; otherwise, false
*/
public static boolean isSwift(Program program) {
List<String> prefixes = List.of("__swift", "swift", ".sw5");
for (MemoryBlock block : program.getMemory().getBlocks()) {
if (prefixes.stream().anyMatch(prefix -> block.getName().startsWith(prefix))) {
return true;
}
}
return false;
}
/**
* Gets a {@link List} of {@link MemoryBlock}s that match the given {@link SwiftSection}
*
* @param section The {@link SwiftSection}
* @param program The {@link Program}
* @return A {@link List} of {@link MemoryBlock}s that match the given {@link SwiftSection}
*/
public static List<MemoryBlock> getSwiftBlocks(SwiftSection section, Program program) {
List<MemoryBlock> result = new ArrayList<>();
for (MemoryBlock block : program.getMemory().getBlocks()) {
for (String sectionName : section.getSwiftSectionNames()) {
if (block.getName().equals(sectionName)) {
result.add(block);
break;
}
}
}
return result;
}
/**
* Reads the integer at the current index and uses it as a relative pointer to read and
* return a string at that location. When the read completes, the {@link BinaryReader} will
* be positioned directly after the initial relative pointer that was read.
*
* @param reader A {@link BinaryReader} positioned at the start of relative string pointer
* @return The read string
* @throws IOException if there was an IO-related problem during the reads
*/
public static String relativeString(BinaryReader reader) throws IOException {
long fieldIndex = reader.getPointerIndex();
int offset = reader.readNextInt();
return reader.readAsciiString(fieldIndex + offset);
}
}
@@ -0,0 +1,130 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift AssociatedTypeDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
public final class AssociatedTypeDescriptor implements SwiftStructure {
/**
* The size (in bytes) of an {@link AssociatedTypeDescriptor} structure
*/
public static final int SIZE = 16;
private String conformingTypeName;
private String protocolTypeName;
private int numAssociatedTypes;
private int associatedTypeRecordSize;
private List<AssociatedTypeRecord> associatedTypeRecords = new ArrayList<>();
/**
* Creates a new {@link AssociatedTypeDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public AssociatedTypeDescriptor(BinaryReader reader) throws IOException {
conformingTypeName = reader.readNext(SwiftUtils::relativeString);
protocolTypeName = reader.readNext(SwiftUtils::relativeString);
numAssociatedTypes = reader.readNextInt();
associatedTypeRecordSize = reader.readNextInt();
for (int i = 0; i < numAssociatedTypes; i++) {
associatedTypeRecords.add(new AssociatedTypeRecord(reader));
}
}
/**
* Gets the conforming type name
*
* @return The conforming type name
*/
public String getConformingTypeName() {
return conformingTypeName;
}
/**
* Gets the protocol type name
*
* @return The protocol type name
*/
public String getProtocolTypeName() {
return protocolTypeName;
}
/**
* Gets the number of associated types
*
* @return The number of associated types
*/
public int getNumAssociatedTypes() {
return numAssociatedTypes;
}
/**
* Gets the associated type record size
*
* @return The associated type record size
*/
public int getAssociatedTypeRecordSize() {
return associatedTypeRecordSize;
}
/**
* Gets the {@link List} of {@link AssociatedTypeRecord}s
*
* @return The {@link List} of {@link AssociatedTypeRecord}s
*/
public List<AssociatedTypeRecord> getAssociatedTypeRecords() {
return associatedTypeRecords;
}
@Override
public String getStructureName() {
return AssociatedTypeDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "associated type descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(SwiftUtils.PTR_STRING, "ConformingTypeName", "");
struct.add(SwiftUtils.PTR_STRING, "ProtocolTypeName", "");
struct.add(DWORD, "NumAssociatedTypes", "");
struct.add(DWORD, "AssociatedTypeRecordSize", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,89 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift AssociatedTypeRecord structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
public final class AssociatedTypeRecord implements SwiftStructure {
/**
* The size (in bytes) of an {@link AssociatedTypeRecord} structure
*/
public static final int SIZE = 8;
private String name;
private String substitutedTypeName;
/**
* Creates a new {@link AssociatedTypeRecord}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public AssociatedTypeRecord(BinaryReader reader) throws IOException {
name = reader.readNext(SwiftUtils::relativeString);
substitutedTypeName = reader.readNext(SwiftUtils::relativeString);
}
/**
* Gets the name
*
* @return The name
*/
public String getName() {
return name;
}
/**
* Gets the substituted type name
*
* @return The substituted type name
*/
public String getSubstitutedTypeName() {
return substitutedTypeName;
}
@Override
public String getStructureName() {
return AssociatedTypeRecord.class.getSimpleName();
}
@Override
public String getDescription() {
return "associated type record";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(SwiftUtils.PTR_STRING, "Name", "");
struct.add(SwiftUtils.PTR_STRING, "SubstitutedTypeName", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,124 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.*;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift BuiltinTypeDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
public final class BuiltinTypeDescriptor implements SwiftStructure {
/**
* The size (in bytes) of a {@link BuiltinTypeDescriptor} structure
*/
public static final int SIZE = 20;
private String typeName;
private int size;
private int alignmentAndFlags;
private int stride;
private int numExtraInhabitants;
/**
* Creates a new {@link BuiltinTypeDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public BuiltinTypeDescriptor(BinaryReader reader) throws IOException {
typeName = reader.readNext(SwiftUtils::relativeString);
size = reader.readNextInt();
alignmentAndFlags = reader.readNextInt();
stride = reader.readNextInt();
numExtraInhabitants = reader.readNextInt();
}
/**
* Gets the type name
*
* @return The type name
*/
public String getTypeName() {
return typeName;
}
/**
* Gets the size
*
* @return The size
*/
public int getSize() {
return size;
}
/**
* Gets the alignment and flags
*
* @return The alignment and flags
*/
public int getAlignmentAndFlags() {
return alignmentAndFlags;
}
/**
* Gets the stride
*
* @return The stride
*/
public int getStride() {
return stride;
}
/**
* Gets the number of extra inhabitants
*
* @return The number of extra inhabitants
*/
public int getNumExtraInhabitants() {
return numExtraInhabitants;
}
@Override
public String getStructureName() {
return BuiltinTypeDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "builtin type descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(SwiftUtils.PTR_STRING, "TypeName", "");
struct.add(DWORD, "Size", "");
struct.add(DWORD, "AlignmentAndFlags", "");
struct.add(DWORD, "Stride", "");
struct.add(DWORD, "NumExtraInhabitants", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,133 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftStructure;
import ghidra.program.model.data.CategoryPath;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift CaptureDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
public final class CaptureDescriptor implements SwiftStructure {
/**
* The size (in bytes) of a {@link CaptureDescriptor} structure
*/
public static final int SIZE = 12;
private int numCaptureTypes;
private int numMetadataSources;
private int numBindings;
private List<CaptureTypeRecord> captureTypeRecords = new ArrayList<>();
private List<MetadataSourceRecord> metadataSourceRecords = new ArrayList<>();
/**
* Creates a new {@link CaptureDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public CaptureDescriptor(BinaryReader reader) throws IOException {
numCaptureTypes = reader.readNextInt();
numMetadataSources = reader.readNextInt();
numBindings = reader.readNextInt();
for (int i = 0; i < numCaptureTypes; i++) {
captureTypeRecords.add(new CaptureTypeRecord(reader));
}
for (int i = 0; i < numMetadataSources; i++) {
metadataSourceRecords.add(new MetadataSourceRecord(reader));
}
}
/**
* Gets the number of capture types
*
* @return The number of capture types
*/
public int getNumCaptureTypes() {
return numCaptureTypes;
}
/**
* Gets the number of metadata sources
*
* @return The number of metadata sources
*/
public int getNumMetadataSources() {
return numMetadataSources;
}
/**
* Gets the number of bindings
*
* @return The number of bindings
*/
public int getNumBindings() {
return numBindings;
}
/**
* Gets the {@link List} of {@link CaptureTypeRecord}s
*
* @return The {@link List} of {@link CaptureTypeRecord}s
*/
public List<CaptureTypeRecord> getCaptureTypeRecords() {
return captureTypeRecords;
}
/**
* Gets the {@link List} of {@link MetadataSourceRecord}s
*
* @return The {@link List} of {@link MetadataSourceRecord}s
*/
public List<MetadataSourceRecord> getMetadataSourceRecords() {
return metadataSourceRecords;
}
@Override
public String getStructureName() {
return CaptureDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "capture descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(DWORD, "NumCaptureTypes", "");
struct.add(DWORD, "NumMetadataSources", "");
struct.add(DWORD, "NumBindings", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,77 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.*;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift CaptureTypeRecord structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
public final class CaptureTypeRecord implements SwiftStructure {
/**
* The size (in bytes) of a {@link CaptureTypeRecord} structure
*/
public static final int SIZE = 4;
private String mangledTypeName;
/**
* Creates a new {@link CaptureTypeRecord}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public CaptureTypeRecord(BinaryReader reader) throws IOException {
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
}
/**
* Gets the mangled type name
*
* @return The mangled type name
*/
public String getMangledTypeName() {
return mangledTypeName;
}
@Override
public String getStructureName() {
return CaptureTypeRecord.class.getSimpleName();
}
@Override
public String getDescription() {
return "capture type record";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,94 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
/**
* Swift ContextDescriptorKind values
*
* @see <a href="https://github.com/apple/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;
}
//---------------------------------------------------------------------------------------------
/**
* This context descriptor represents a module
*/
public static final int MODULE = 0;
/**
* This context descriptor represents an extension
*/
public static final int EXTENSION = 1;
/**
* This context descriptor represents an anonymous possibly-generic context such as a function
* body
*/
public static final int ANONYMOUS = 2;
/**
* This context descriptor represents a protocol context
*/
public static final int PROTOCOL = 3;
/**
* This context descriptor represents an opaque type alias
*/
public static final int OPAQUE_TYPE = 4;
/**
* First kind that represents a type of any sort
*/
public static final int TYPE_FIRST = 16;
/**
* This context descriptor represents a class
*/
public static final int CLASS = TYPE_FIRST;
/**
* This context descriptor represents a struct
*/
public static final int STRUCT = TYPE_FIRST + 1;
/**
* This context descriptor represents an enum
*/
public static final int ENUM = TYPE_FIRST + 2;
/**
* Last kind that represents a type of any sort
*/
public static final int TYPE_LAST = 31;
}
@@ -0,0 +1,72 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift entry point
*/
public final class EntryPoint implements SwiftStructure {
/**
* The size (in bytes) of an {@link EntryPoint} structure
*/
public static final int SIZE = 4;
private int entryPoint;
/**
* Creates a new {@link EntryPoint}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public EntryPoint(BinaryReader reader) throws IOException {
entryPoint = reader.readNextInt();
}
/**
* Gets the entry point
*
* @return The entry point
*/
public int getEntryPoint() {
return entryPoint;
}
@Override
public String getStructureName() {
return EntryPoint.class.getSimpleName();
}
@Override
public String getDescription() {
return "entry point";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return SwiftUtils.PTR_RELATIVE;
}
}
@@ -0,0 +1,141 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.*;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift FieldDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
public final class FieldDescriptor implements SwiftStructure {
/**
* The size (in bytes) of a {@link FieldDescriptor} structure
*/
public static final int SIZE = 16;
private String mangledTypeName;
private int superclass;
private int kind;
private int fieldRecordSize;
private int numFields;
private List<FieldRecord> fieldRecords = new ArrayList<>();
/**
* Creates a new {@link FieldDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public FieldDescriptor(BinaryReader reader) throws IOException {
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
superclass = reader.readNextInt();
kind = reader.readNextUnsignedShort();
fieldRecordSize = reader.readNextUnsignedShort();
numFields = reader.readNextInt();
for (int i = 0; i < numFields; i++) {
fieldRecords.add(new FieldRecord(reader));
}
}
/**
* Gets the mangled type name
*
* @return The mangled type name
*/
public String getMangledTypeName() {
return mangledTypeName;
}
/**
* Gets the superclass
*
* @return The superclass
*/
public int getSuperclass() {
return superclass;
}
/**
* Gets the kind
*
* @return The kind
*/
public int getKind() {
return kind;
}
/**
* Gets the field record size
*
* @return The field record size
*/
public int getFieldRecordSize() {
return fieldRecordSize;
}
/**
* Gets the number of fields
*
* @return The number of fields
*/
public int getNumFields() {
return numFields;
}
/**
* Gets the {@link List} of {@link FieldRecord}s
*
* @return The {@link List} of {@link FieldRecord}s
*/
public List<FieldRecord> getFieldRecords() {
return fieldRecords;
}
@Override
public String getStructureName() {
return FieldDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "field descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
struct.add(SwiftUtils.PTR_RELATIVE, "Superclass", "");
struct.add(WORD, "Kind", "");
struct.add(WORD, "FieldRecordSize", "");
struct.add(DWORD, "NumFields", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,100 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.*;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift FieldRecord structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
public final class FieldRecord implements SwiftStructure {
/**
* The size (in bytes) of a {@link FieldRecord} structure
*/
public static final int SIZE = 12;
private int flags;
private String mangledTypeName;
private String fieldName;
/**
* Creates a new {@link FieldRecord}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public FieldRecord(BinaryReader reader) throws IOException {
flags = reader.readNextInt();
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
fieldName = reader.readNext(SwiftUtils::relativeString);
}
/**
* Gets the flags
*
* @return The flags
*/
public int getFlags() {
return flags;
}
/**
* Gets the mangled type name
*
* @return The mangled type name
*/
public String getMangledTypeName() {
return mangledTypeName;
}
/**
* Gets the field name
*
* @return The field name
*/
public String getFieldName() {
return fieldName;
}
@Override
public String getStructureName() {
return FieldRecord.class.getSimpleName();
}
@Override
public String getDescription() {
return "field record";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(DWORD, "Flags", "");
struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
struct.add(SwiftUtils.PTR_STRING, "FieldName", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,88 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.*;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift MetadataSourceRecord structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
public final class MetadataSourceRecord implements SwiftStructure {
/**
* The size (in bytes) of a {@link MetadataSourceRecord} structure
*/
public static final int SIZE = 8;
private String mangledTypeName;
private String mangledMetadataSource;
/**
* Creates a new {@link MetadataSourceRecord}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public MetadataSourceRecord(BinaryReader reader) throws IOException {
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
mangledMetadataSource = reader.readNext(SwiftUtils::relativeString);
}
/**
* Gets the mangled type name
*
* @return The mangled type name
*/
public String getMangledTypeName() {
return mangledTypeName;
}
/**
* Gets the mangled metadata source
*
* @return The mangled metadata source
*/
public String getMangledMetadataSource() {
return mangledMetadataSource;
}
@Override
public String getStructureName() {
return MetadataSourceRecord.class.getSimpleName();
}
@Override
public String getDescription() {
return "metadata source record";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(SwiftUtils.PTR_STRING, "MangledTypeName", "");
struct.add(SwiftUtils.PTR_STRING, "MangledMetadataSource", "");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,98 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftStructure;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift MultiPayloadEnumDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/RemoteInspection/Records.h">swift/RemoteInspection/Records.h</a>
*/
public final class MultiPayloadEnumDescriptor implements SwiftStructure {
/**
* The size (in bytes) of a {@link MultiPayloadEnumDescriptor} structure. This size does not
* take into account the size of the <code>contents</code> array.
*
* @see #getContentsSize()
*/
public static final int SIZE = 4;
private String typeName;
private int[] contents;
/**
* Creates a new {@link MultiPayloadEnumDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public MultiPayloadEnumDescriptor(BinaryReader reader) throws IOException {
typeName = reader.readNext(SwiftUtils::relativeString);
int size = (reader.readNextInt() >> 16) & 0xffff;
reader.setPointerIndex(reader.getPointerIndex() - 4);
contents = reader.readNextIntArray(size);
}
/**
* Gets the type name
*
* @return The type name
*/
public String getTypeName() {
return typeName;
}
/**
* Gets the contents
*
* @return The contents
*/
public int[] getContents() {
return contents;
}
/**
* Gets the size of the contents in bytes
*
* @return The size of the contents in bytes
*/
public long getContentsSize() {
return contents.length * Integer.BYTES;
}
@Override
public String getStructureName() {
return MultiPayloadEnumDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "multipayload enum descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return SwiftUtils.PTR_STRING;
}
}
@@ -0,0 +1,138 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.CategoryPath;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetClassDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public final class TargetClassDescriptor extends TargetTypeContextDescriptor {
private int superclassType;
private int metadataNegativeSizeInWords;
private int metadataPositiveSizeInWords;
private int numImmediateMembers;
private int numFields;
/**
* Creates a new {@link TargetClassDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public TargetClassDescriptor(BinaryReader reader) throws IOException {
super(reader);
superclassType = reader.readNextInt();
metadataNegativeSizeInWords = reader.readNextInt();
metadataPositiveSizeInWords = reader.readNextInt();
numImmediateMembers = reader.readNextInt();
numFields = reader.readNextInt();
}
/**
* Gets the type of the superclass, expressed as a mangled type name that can refer to the
* generic arguments of the subclass type
*
* @return The type of the superclass, expressed as a mangled type name that can refer to the
* generic arguments of the subclass type
*/
public int getSuperclassType() {
return superclassType;
}
/**
* If this descriptor does not have a resilient superclass, this is the negative size of
* metadata objects of this class (in words). If this descriptor has a resilient superclass,
* this is a reference to a cache holding the metadata's extents.
*
* @return The negative size of metadata objects of this class (in words) or a reference to a
* cache holding the metadata's extents
*/
public int getMetadataNegativeSizeInWords() {
return metadataNegativeSizeInWords;
}
/**
* If this descriptor does not have a resilient superclass, this is the positive size of
* metadata objects of this class (in words). Otherwise, these flags are used to do things like
* indicate the presence of an Objective-C resilient class stub.
*
* @return The positive size of metadata objects of this class (in words) or flags used to do
* things like indicate the presence of an Objective-C resilient class stub.
*/
public int getMetadataPositiveSizeInWords() {
return metadataPositiveSizeInWords;
}
/**
* Gets the number of additional members added by this class to the class metadata
*
* @return The number of additional members added by this class to the class metadata
*/
public int getNumImmediateMembers() {
return numImmediateMembers;
}
/**
* Gets the number of stored properties in the class, not including its superclasses. If there
* is a field offset vector, this is its length.
*
* @return The number of stored properties in the class, not including its superclasses.
* If there is a field offset vector, this is its length.
*/
public int getNumFields() {
return numFields;
}
@Override
public String getStructureName() {
return TargetClassDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "class descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(super.toDataType(), super.getStructureName(), "");
struct.add(SwiftUtils.PTR_STRING, "SuperclassType",
"The type of the superclass, expressed as a mangled type name that can refer to the generic arguments of the subclass type");
struct.add(DWORD, "MetadataNegativeSizeInWords",
"If this descriptor does not have a resilient superclass, this is the negative size of metadata objects of this class (in words)");
struct.add(DWORD, "MetadataPositiveSizeInWords",
"If this descriptor does not have a resilient superclass, this is the positive size of metadata objects of this class (in words)");
struct.add(DWORD, "NumImmediateMembers",
"The number of additional members added by this class to the class metadata");
struct.add(DWORD, "NumFields",
"The number of stored properties in the class, not including its superclasses. If there is a field offset vector, this is its length.");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,94 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.*;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetContextDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetContextDescriptor implements SwiftStructure {
private int flags;
private int parent;
/**
* Create a new {@link TargetContextDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public TargetContextDescriptor(BinaryReader reader) throws IOException {
flags = reader.readNextInt();
parent = reader.readNextInt();
}
/**
* Gets the flags
*
* @return The flags
*/
public int getFlags() {
return flags;
}
/**
* Gets the parent's relative offset
*
* @return The parent's relative offset
*/
public int getParent() {
return parent;
}
@Override
public String getStructureName() {
return getMyStructureName();
}
@Override
public String getDescription() {
return "context descriptor";
}
/**
* Gets this class's structure name (will not be affected by subclass's name)
*
* @return This class's structure name
*/
private final String getMyStructureName() {
return TargetContextDescriptor.class.getSimpleName();
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getMyStructureName(), 0);
struct.add(DWORD, "Flags",
"Flags describing the context, including its kind and format version");
struct.add(SwiftUtils.PTR_RELATIVE, "Parent",
"The parent context, or null if this is a top-level context");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,88 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.CategoryPath;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetEnumDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
private int numPayloadCasesAndPayloadSizeOffset;
private int numEmptyCases;
/**
* Creates a new {@link TargetEnumDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public TargetEnumDescriptor(BinaryReader reader) throws IOException {
super(reader);
numPayloadCasesAndPayloadSizeOffset = reader.readNextInt();
numEmptyCases = reader.readNextInt();
}
/**
* Gets the number of non-empty cases in the enum are in the low 24 bits; the offset of the
* payload size in the metadata record in words, if any, is stored in the high 8 bits;
* @return The number of non-empty cases in the enum and the offset of the payload size
*/
public int getNumPayloadCasesAndPayloadSizeOffset() {
return numPayloadCasesAndPayloadSizeOffset;
}
/**
* Gets the number of empty cases in the enum
*
* @return The number of empty cases in the enum
*/
public int getNumEmptyCases() {
return numEmptyCases;
}
@Override
public String getStructureName() {
return TargetEnumDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "enum descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(super.toDataType(), super.getStructureName(), "");
struct.add(DWORD, "NumPayloadCasesAndPayloadSizeOffset",
"The number of non-empty cases in the enum are in the low 24 bits; the offset of the payload size in the metadata record in words, if any, is stored in the high 8 bits.");
struct.add(DWORD, "NumEmptyCases", "The number of empty cases in the enum");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,109 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.*;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetProtocolConformanceDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public final class TargetProtocolConformanceDescriptor implements SwiftStructure {
private int protocolDescriptor;
private int nominalTypeDescriptor;
private int protocolWitnessTable;
private int conformanceFlags;
/**
* Creates a new {@link TargetProtocolConformanceDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public TargetProtocolConformanceDescriptor(BinaryReader reader) throws IOException {
protocolDescriptor = reader.readNextInt();
nominalTypeDescriptor = reader.readNextInt();
protocolWitnessTable = reader.readNextInt();
conformanceFlags = reader.readNextInt();
}
/**
* Gets the protocol being conformed to
*
* @return The protocol being conformed to
*/
public int getProtocolDescriptor() {
return protocolDescriptor;
}
/**
* Gets some description of the type that conforms to the protocol
*
* @return Some description of the type that conforms to the protocol
*/
public int getNominalTypeDescriptor() {
return nominalTypeDescriptor;
}
/**
* Gets the witness table pattern, which may also serve as the witness table
*
* @return The witness table pattern, which may also serve as the witness table
*/
public int getProtocolWitnessTable() {
return protocolWitnessTable;
}
/**
* Gets various flags, including the kind of conformance
*
* @return Various flags, including the kind of conformance
*/
public int getConformanceFlags() {
return conformanceFlags;
}
@Override
public String getStructureName() {
return TargetProtocolConformanceDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "protocol conformance descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(DWORD, "ProtocolDescriptor", "The protocol being conformed to");
struct.add(SwiftUtils.PTR_RELATIVE, "NominalTypeDescriptor",
"Some description of the type that conforms to the protocol");
struct.add(DWORD, "ProtocolWitnessTable",
"The witness table pattern, which may also serve as the witness table");
struct.add(DWORD, "ConformanceFlags", "Various flags, including the kind of conformance");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,118 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.CategoryPath;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetProtocolDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public final class TargetProtocolDescriptor extends TargetContextDescriptor {
private String name;
private int numRequirementsInSig;
private int numRequirements;
private int associatedTypeNames;
/**
* Creates a new {@link TargetProtocolDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public TargetProtocolDescriptor(BinaryReader reader) throws IOException {
super(reader);
name = reader.readNext(SwiftUtils::relativeString);
numRequirementsInSig = reader.readNextInt();
numRequirements = reader.readNextInt();
associatedTypeNames = reader.readNextInt();
}
/**
* Gets the name of the protocol
*
* @return The name of the protocol
*/
public String getName() {
return name;
}
/**
* Gets the number of generic requirements in the requirement signature of the protocol
*
* @return The number of generic requirements in the requirement signature of the protocol
*/
public int getNumRequirementsInSignature() {
return numRequirementsInSig;
}
/**
* Gets the number of requirements in the protocol
*
* @return The number of requirements in the protocol
*/
public int getNumRequirements() {
return numRequirements;
}
/**
* Gets the associated type names
*
* @return The associated type names
*/
public int getAssociatedTypeNames() {
return associatedTypeNames; // TODO: it's a list...improve
}
@Override
public String toString() {
return name;
}
@Override
public String getStructureName() {
return TargetProtocolDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "protocol descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(super.toDataType(), super.getStructureName(), "");
struct.add(SwiftUtils.PTR_STRING, "Name", "The name of the protocol");
struct.add(DWORD, "NumRequirementsInSignature",
"The number of generic requirements in the requirement signature of the protocol");
struct.add(DWORD, "NumRequirements", "The number of requirements in the protocol");
struct.add(DWORD, "AssociatedTypeNames",
"Associated type names, as a space-separated list in the same order as the requirements");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,92 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.CategoryPath;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetStructDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public final class TargetStructDescriptor extends TargetTypeContextDescriptor {
private int numFields;
private int fieldOffsetVectorOffset;
/**
* Creates a new {@link TargetStructDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public TargetStructDescriptor(BinaryReader reader) throws IOException {
super(reader);
numFields = reader.readNextInt();
fieldOffsetVectorOffset = reader.readNextInt();
}
/**
* Gets the number of stored properties in the struct. If there is a field offset vector,
* this is its length.
* @return The number of stored properties in the struct. If there is a field offset vector,
* this is its length.
*/
public int getNumFields() {
return numFields;
}
/**
* Gets the offset of the field offset vector for this struct's stored properties in its
* metadata, if any. 0 means there is no field offset vector.
*
* @return The offset of the field offset vector for this struct's stored properties in its
* metadata, if any. 0 means there is no field offset vector.
*/
public int getFieldOffsetVectorOffset() {
return fieldOffsetVectorOffset;
}
@Override
public String getStructureName() {
return TargetStructDescriptor.class.getSimpleName();
}
@Override
public String getDescription() {
return "struct descriptor";
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getStructureName(), 0);
struct.add(super.toDataType(), super.getStructureName(), "");
struct.add(DWORD, "NumFields",
"The number of stored properties in the struct. If there is a field offset vector, this is its length.");
struct.add(DWORD, "FieldOffsetVectorOffset",
"The offset of the field offset vector for this struct's stored properties in its metadata, if any. 0 means there is no field offset vector.");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}
@@ -0,0 +1,112 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.swift.types;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* Represents a Swift TargetTypeContextDescriptor structure
*
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/ABI/Metadata.h">swift/ABI/Metadata.h</a>
*/
public class TargetTypeContextDescriptor extends TargetContextDescriptor {
private String name;
private int accessFunctionPtr;
private int fields;
/**
* Creates a new {@link TargetTypeContextDescriptor}
*
* @param reader A {@link BinaryReader} positioned at the start of the structure
* @throws IOException if there was an IO-related problem creating the structure
*/
public TargetTypeContextDescriptor(BinaryReader reader) throws IOException {
super(reader);
name = reader.readNext(SwiftUtils::relativeString);
accessFunctionPtr = reader.readNextInt();
fields = reader.readNextInt();
}
/**
* Gets the name of the type
*
* @return The name of the type
*/
public String getName() {
return name;
}
/**
* Gets the pointer to the metadata access function for this type
*
* @return The pointer to the metadata access function for this type
*/
public int getAccessFunctionPtr() {
return accessFunctionPtr;
}
/**
* Gets the pointer to the field descriptor for the type, if any
*
* @return The pointer to the field descriptor for the type, if any
*/
public int getFields() {
return fields;
}
@Override
public String getStructureName() {
return getMyStructureName();
}
@Override
public String getDescription() {
return "type context descriptor";
}
@Override
public String toString() {
return name;
}
/**
* Gets this class's structure name (will not be affected by subclass's name)
*
* @return This class's structure name
*/
private final String getMyStructureName() {
return TargetTypeContextDescriptor.class.getSimpleName();
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType(getMyStructureName(), 0);
struct.add(super.toDataType(), super.getStructureName(), "");
struct.add(SwiftUtils.PTR_STRING, "Name", "The name of the type");
struct.add(SwiftUtils.PTR_RELATIVE, "AccessFunctionPtr",
"A pointer to the metadata access function for this type");
struct.add(SwiftUtils.PTR_RELATIVE, "Fields",
"A pointer to the field descriptor for the type, if any");
struct.setCategoryPath(new CategoryPath(DATA_TYPE_CATEGORY));
return struct;
}
}