mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 13:42:06 +00:00
Merge remote-tracking branch 'origin/GP-2085_ryanmkurtz_Swift-Metadata--SQUASHED'
This commit is contained in:
commit
176bdea28a
@ -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,506 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.bin.format.swift;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.app.util.bin.format.swift.types.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Parses marks up, and provide access to Swift type metadata
|
||||
*/
|
||||
public class SwiftTypeMetadata {
|
||||
|
||||
private Program program;
|
||||
private TaskMonitor monitor;
|
||||
private MessageLog log;
|
||||
|
||||
private List<EntryPoint> entryPoints = new ArrayList<>();
|
||||
private List<BuiltinTypeDescriptor> builtinTypeDescriptors = new ArrayList<>();
|
||||
private List<FieldDescriptor> fieldDescriptors = new ArrayList<>();
|
||||
private List<AssociatedTypeDescriptor> associatedTypeDescriptors = new ArrayList<>();
|
||||
private List<CaptureDescriptor> captureDescriptors = new ArrayList<>();
|
||||
private List<MultiPayloadEnumDescriptor> mpEnumDescriptors = new ArrayList<>();
|
||||
private List<TargetTypeContextDescriptor> typeDescriptors = new ArrayList<>();
|
||||
private List<TargetProtocolDescriptor> protocolDescriptors = new ArrayList<>();
|
||||
private List<TargetProtocolConformanceDescriptor> protocolConformanceDescriptors =
|
||||
new ArrayList<>();
|
||||
|
||||
private List<SwiftStructureInfo> markupList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a new {@link SwiftTypeMetadata}
|
||||
*
|
||||
* @param program The {@link Program}
|
||||
* @param monitor A cancellable task monitor
|
||||
* @param log The log
|
||||
* @throws IOException if there was an IO-related error
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
public SwiftTypeMetadata(Program program, TaskMonitor monitor, MessageLog log)
|
||||
throws IOException, CancelledException {
|
||||
this.program = program;
|
||||
this.monitor = monitor;
|
||||
this.log = log;
|
||||
|
||||
parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link SwiftTypeMetadata}
|
||||
*
|
||||
* @throws IOException if there was an IO-related error
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parse() throws IOException, CancelledException {
|
||||
try (ByteProvider provider =
|
||||
MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false)) {
|
||||
BinaryReader reader = new BinaryReader(provider, !program.getLanguage().isBigEndian());
|
||||
|
||||
parseEntryPoints(SwiftSection.BLOCK_ENTRY, reader);
|
||||
parseBuiltinTypeDescriptors(SwiftSection.BLOCK_BUILTIN, reader);
|
||||
parseFieldDescriptors(SwiftSection.BLOCK_FIELDMD, reader);
|
||||
parseAssociatedTypeDescriptors(SwiftSection.BLOCK_ASSOCTY, reader);
|
||||
parseCaptureTypeDescriptors(SwiftSection.BLOCK_CAPTURE, reader);
|
||||
parseMultiPayloadEnumDescriptors(SwiftSection.BLOCK_MPENUM, reader);
|
||||
parseProtocolDescriptors(SwiftSection.BLOCK_PROTOCS, reader);
|
||||
parseProtocolConformanceDescriptors(SwiftSection.BLOCK_CONFORM, reader);
|
||||
parseTypeDescriptors(SwiftSection.BLOCK_TYPES, reader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the entry point(s)
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the entry point(s)
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parseEntryPoints(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
monitor.setMessage("Parsing Swift entry point(s)...");
|
||||
monitor.setIndeterminate(true);
|
||||
try {
|
||||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
monitor.checkCancelled();
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
EntryPoint entryPoint = new EntryPoint(reader);
|
||||
entryPoints.add(entryPoint);
|
||||
markupList.add(new SwiftStructureInfo(entryPoint,
|
||||
new SwiftStructureAddress(blockStart, null)));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse entry point(s) from section '" + section + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link BuiltinTypeDescriptor}s
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the descriptors
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parseBuiltinTypeDescriptors(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
monitor.setMessage("Parsing Swift builtin type descriptors...");
|
||||
monitor.setIndeterminate(true);
|
||||
try {
|
||||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
while (i + BuiltinTypeDescriptor.SIZE <= block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
BuiltinTypeDescriptor descriptor = new BuiltinTypeDescriptor(reader);
|
||||
builtinTypeDescriptors.add(descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||
i += BuiltinTypeDescriptor.SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse builtin type descriptors from section '" + section + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link FieldDescriptor}s
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the descriptors
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parseFieldDescriptors(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
monitor.setMessage("Parsing Swift field descriptors...");
|
||||
monitor.setIndeterminate(true);
|
||||
try {
|
||||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
while (i + FieldDescriptor.SIZE <= block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
FieldDescriptor descriptor = new FieldDescriptor(reader);
|
||||
fieldDescriptors.add(descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||
List<FieldRecord> records = descriptor.getFieldRecords();
|
||||
i += FieldDescriptor.SIZE;
|
||||
for (int j = 0; j < records.size(); j++) {
|
||||
FieldRecord record = records.get(j);
|
||||
markupList.add(new SwiftStructureInfo(record,
|
||||
new SwiftStructureAddress(blockStart.add(i + j * FieldRecord.SIZE),
|
||||
null)));
|
||||
}
|
||||
i += descriptor.getNumFields() * FieldRecord.SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse field descriptors from section '" + section + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link AssociatedTypeDescriptor}s
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the descriptors
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parseAssociatedTypeDescriptors(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
monitor.setMessage("Parsing Swift associated type descriptors...");
|
||||
monitor.setIndeterminate(true);
|
||||
try {
|
||||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
while (i + AssociatedTypeDescriptor.SIZE <= block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
AssociatedTypeDescriptor descriptor = new AssociatedTypeDescriptor(reader);
|
||||
associatedTypeDescriptors.add(descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||
List<AssociatedTypeRecord> records = descriptor.getAssociatedTypeRecords();
|
||||
i += AssociatedTypeDescriptor.SIZE;
|
||||
for (int j = 0; j < records.size(); j++) {
|
||||
AssociatedTypeRecord record = records.get(j);
|
||||
markupList.add(new SwiftStructureInfo(record,
|
||||
new SwiftStructureAddress(
|
||||
blockStart.add(i + j * AssociatedTypeRecord.SIZE), null)));
|
||||
}
|
||||
i += descriptor.getNumAssociatedTypes() * AssociatedTypeRecord.SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse associated type descriptors from section '" + section + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link CaptureDescriptor}s
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the descriptors
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parseCaptureTypeDescriptors(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
monitor.setMessage("Parsing Swift capture descriptors...");
|
||||
monitor.setIndeterminate(true);
|
||||
try {
|
||||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
while (i + CaptureDescriptor.SIZE <= block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
CaptureDescriptor descriptor = new CaptureDescriptor(reader);
|
||||
captureDescriptors.add(descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||
List<CaptureTypeRecord> records = descriptor.getCaptureTypeRecords();
|
||||
i += CaptureDescriptor.SIZE;
|
||||
for (int j = 0; j < records.size(); j++) {
|
||||
CaptureTypeRecord record = records.get(j);
|
||||
markupList.add(new SwiftStructureInfo(record,
|
||||
new SwiftStructureAddress(
|
||||
blockStart.add(i + j * CaptureTypeRecord.SIZE), null)));
|
||||
}
|
||||
i += descriptor.getNumCaptureTypes() * CaptureTypeRecord.SIZE;
|
||||
List<MetadataSourceRecord> sourceRecords =
|
||||
descriptor.getMetadataSourceRecords();
|
||||
for (int j = 0; j < sourceRecords.size(); j++) {
|
||||
MetadataSourceRecord record = sourceRecords.get(j);
|
||||
markupList.add(new SwiftStructureInfo(record,
|
||||
new SwiftStructureAddress(
|
||||
blockStart.add(i + j * MetadataSourceRecord.SIZE), null)));
|
||||
}
|
||||
i += descriptor.getNumMetadataSources() * MetadataSourceRecord.SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse capture descriptors from section '" + section + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link MultiPayloadEnumDescriptor}s
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the descriptors
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parseMultiPayloadEnumDescriptors(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
monitor.setMessage("Parsing Swift multipayload enum descriptors...");
|
||||
monitor.setIndeterminate(true);
|
||||
try {
|
||||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
while (i < block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
MultiPayloadEnumDescriptor descriptor = new MultiPayloadEnumDescriptor(reader);
|
||||
mpEnumDescriptors.add(descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||
i += MultiPayloadEnumDescriptor.SIZE + descriptor.getContentsSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse multipayload enum descriptors from section '" + section + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link TargetProtocolDescriptor}s
|
||||
*
|
||||
* @param section The section name that contains the descriptors
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parseProtocolDescriptors(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
monitor.setMessage("Parsing Swift protocol descriptors...");
|
||||
monitor.setIndeterminate(true);
|
||||
try {
|
||||
List<SwiftStructureAddress> addrPairs = parsePointerTable(section, reader);
|
||||
for (SwiftStructureAddress addrPair : addrPairs) {
|
||||
reader.setPointerIndex(addrPair.structAddr().getOffset());
|
||||
TargetProtocolDescriptor descriptor = new TargetProtocolDescriptor(reader);
|
||||
protocolDescriptors.add(descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(addrPair.structAddr(), addrPair.pointerAddr())));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse protocol descriptors from section '" + section + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link TargetProtocolConformanceDescriptor}s
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the descriptors
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parseProtocolConformanceDescriptors(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
monitor.setMessage("Parsing Swift protocol conformance descriptors...");
|
||||
monitor.setIndeterminate(true);
|
||||
try {
|
||||
List<SwiftStructureAddress> addrPairs = parsePointerTable(section, reader);
|
||||
for (SwiftStructureAddress addrPair : addrPairs) {
|
||||
reader.setPointerIndex(addrPair.structAddr().getOffset());
|
||||
TargetProtocolConformanceDescriptor descriptor =
|
||||
new TargetProtocolConformanceDescriptor(reader);
|
||||
protocolConformanceDescriptors.add(descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(addrPair.structAddr(),
|
||||
addrPair.pointerAddr())));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse protocol conformance descriptors from section '" + section +
|
||||
"'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link TargetTypeContextDescriptor}s
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the descriptors
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private void parseTypeDescriptors(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
monitor.setMessage("Parsing Swift type descriptors...");
|
||||
monitor.setIndeterminate(true);
|
||||
try {
|
||||
List<SwiftStructureAddress> addrPairs = parsePointerTable(section, reader);
|
||||
for (SwiftStructureAddress addrPair : addrPairs) {
|
||||
reader.setPointerIndex(addrPair.structAddr().getOffset());
|
||||
long origIndex = reader.getPointerIndex();
|
||||
TargetTypeContextDescriptor descriptor = new TargetTypeContextDescriptor(reader);
|
||||
reader.setPointerIndex(origIndex);
|
||||
int contextDescriptorKind = ContextDescriptorKind.getKind(descriptor.getFlags());
|
||||
descriptor = switch (contextDescriptorKind) {
|
||||
case ContextDescriptorKind.CLASS:
|
||||
yield new TargetClassDescriptor(reader);
|
||||
case ContextDescriptorKind.STRUCT:
|
||||
yield new TargetStructDescriptor(reader);
|
||||
case ContextDescriptorKind.ENUM:
|
||||
yield new TargetEnumDescriptor(reader);
|
||||
default:
|
||||
log("Unrecognized type descriptor %d at index: 0x%x"
|
||||
.formatted(contextDescriptorKind, origIndex));
|
||||
yield null;
|
||||
};
|
||||
if (descriptor != null) {
|
||||
typeDescriptors.add(descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(addrPair.structAddr(), addrPair.pointerAddr())));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse type descriptors from section '" + section + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a table of pointers to {@link SwiftStructure}s found in the given section
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the pointer table
|
||||
* @param reader A {@link BinaryReader}
|
||||
* @return A {@link List} of {@link SwiftStructureAddress}s
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
private List<SwiftStructureAddress> parsePointerTable(SwiftSection section, BinaryReader reader)
|
||||
throws CancelledException {
|
||||
final int POINTER_SIZE = 4;
|
||||
List<SwiftStructureAddress> result = new ArrayList<>();
|
||||
try {
|
||||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockAddr = block.getStart();
|
||||
for (int i = 0; i < block.getSize(); i += POINTER_SIZE) {
|
||||
monitor.checkCancelled();
|
||||
reader.setPointerIndex(blockAddr.getOffset() + i);
|
||||
Address pointerAddr = blockAddr.add(i);
|
||||
int offset = reader.readInt(pointerAddr.getOffset());
|
||||
if (offset == 0) {
|
||||
break;
|
||||
}
|
||||
Address structAddr = pointerAddr.add(offset);
|
||||
result.add(new SwiftStructureAddress(structAddr, pointerAddr));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse Swift struction pointers from section '" + section + "'");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks up this {@link SwiftTypeMetadata} with data structures and comments
|
||||
*
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
public void markup() throws CancelledException {
|
||||
monitor.setMessage("Marking up Swift structures...");
|
||||
monitor.initialize(markupList.size());
|
||||
for (SwiftStructureInfo structInfo : markupList) {
|
||||
monitor.checkCancelled();
|
||||
monitor.incrementProgress(1);
|
||||
try {
|
||||
SwiftStructure struct = structInfo.struct();
|
||||
DataType dt = struct.toDataType();
|
||||
DataUtilities.createData(program, structInfo.addr().structAddr(), dt, -1,
|
||||
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
||||
if (structInfo.addr().pointerAddr() != null) {
|
||||
PointerTypedef relativePtrDataType =
|
||||
new PointerTypedef(null, dt, 4, null, PointerType.RELATIVE);
|
||||
DataUtilities.createData(program, structInfo.addr().pointerAddr(),
|
||||
relativePtrDataType, -1, ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
||||
}
|
||||
}
|
||||
catch (CodeUnitInsertionException | DuplicateNameException | IOException e) {
|
||||
log("Failed to markup: " + structInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to perform logging
|
||||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
private void log(String message) {
|
||||
log.appendMsg(SwiftTypeMetadata.class.getSimpleName(), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link Address} of a {@link SwiftStructure} and the optional {@link Address} of its
|
||||
* pointer
|
||||
*
|
||||
* @param structAddr The {@link Address} of a {@link SwiftStructure}
|
||||
* @param pointerAddr The {@link Address} of a pointer to a {@link SwiftStructure} (could be
|
||||
* null if there is no associated pointer}
|
||||
*/
|
||||
private record SwiftStructureAddress(Address structAddr, Address pointerAddr) {}
|
||||
|
||||
/**
|
||||
* Information about a {@link SwiftStructure}
|
||||
*
|
||||
* @param struct The {@link SwiftStructure}
|
||||
* @param addr The {@link SwiftStructureAddress address} of the {@link SwiftStructure}
|
||||
*/
|
||||
private record SwiftStructureInfo(SwiftStructure struct, SwiftStructureAddress addr) {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "%s %s".formatted(struct.getDescription(), addr);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user