mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-3535: Improved Swift support
This commit is contained in:
parent
74d52deabf
commit
32a0cf750b
104 changed files with 6438 additions and 161 deletions
|
@ -31,6 +31,8 @@ public class SwiftTypeMetadataAnalyzer extends AbstractAnalyzer {
|
|||
private static final String NAME = "Swift Type Metadata Analyzer";
|
||||
private static final String DESCRIPTION = "Discovers Swift type metadata records.";
|
||||
|
||||
private SwiftTypeMetadata typeMetadata;
|
||||
|
||||
public SwiftTypeMetadataAnalyzer() {
|
||||
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
|
||||
setDefaultEnablement(true);
|
||||
|
@ -45,8 +47,11 @@ public class SwiftTypeMetadataAnalyzer extends AbstractAnalyzer {
|
|||
@Override
|
||||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||
throws CancelledException {
|
||||
if (typeMetadata != null) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
SwiftTypeMetadata typeMetadata = new SwiftTypeMetadata(program, monitor, log);
|
||||
typeMetadata = new SwiftTypeMetadata(program, monitor, log);
|
||||
typeMetadata.markup();
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
@ -54,4 +59,9 @@ public class SwiftTypeMetadataAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analysisEnded(Program program) {
|
||||
typeMetadata = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,9 @@ public enum SwiftSection {
|
|||
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");
|
||||
BLOCK_TYPES("__swift5_types", "swift5_type_metadata", ".sw5tymd"),
|
||||
BLOCK_ENTRY("__swift5_entry", "swift5_entry", ".sw5entr"),
|
||||
BLOCK_SWIFTAST("__swift_ast", ".swift_ast", "swiftast");
|
||||
|
||||
private List<String> sectionNames;
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
package ghidra.app.util.bin.format.swift;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.app.util.bin.format.swift.types.*;
|
||||
|
@ -43,11 +42,11 @@ public class SwiftTypeMetadata {
|
|||
|
||||
private List<EntryPoint> entryPoints = new ArrayList<>();
|
||||
private List<BuiltinTypeDescriptor> builtinTypeDescriptors = new ArrayList<>();
|
||||
private List<FieldDescriptor> fieldDescriptors = new ArrayList<>();
|
||||
private Map<Long, FieldDescriptor> fieldDescriptors = new HashMap<>();
|
||||
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 Map<String, TargetTypeContextDescriptor> typeDescriptors = new HashMap<>();
|
||||
private List<TargetProtocolDescriptor> protocolDescriptors = new ArrayList<>();
|
||||
private List<TargetProtocolConformanceDescriptor> protocolConformanceDescriptors =
|
||||
new ArrayList<>();
|
||||
|
@ -72,6 +71,69 @@ public class SwiftTypeMetadata {
|
|||
parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the entry points}
|
||||
*/
|
||||
public List<EntryPoint> getEntryPoints() {
|
||||
return entryPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the built-in type descriptors}
|
||||
*/
|
||||
public List<BuiltinTypeDescriptor> getBuiltinTypeDescriptors() {
|
||||
return builtinTypeDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the field descriptors}
|
||||
*/
|
||||
public Map<Long, FieldDescriptor> getFieldDescriptors() {
|
||||
return fieldDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the associated type descriptors}
|
||||
*/
|
||||
public List<AssociatedTypeDescriptor> getAssociatedTypeDescriptor() {
|
||||
return associatedTypeDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the capture descriptors}
|
||||
*/
|
||||
public List<CaptureDescriptor> getCaptureDescriptors() {
|
||||
return captureDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the multi-payload enum descriptors}
|
||||
*/
|
||||
public List<MultiPayloadEnumDescriptor> getMultiPayloadEnumDescriptors() {
|
||||
return mpEnumDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the type descriptors}
|
||||
*/
|
||||
public Map<String, TargetTypeContextDescriptor> getTargetTypeContextDescriptors() {
|
||||
return typeDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the target protocol descriptors}
|
||||
*/
|
||||
public List<TargetProtocolDescriptor> getTargetProtocolDescriptors() {
|
||||
return protocolDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the target protocol conformance descriptors}
|
||||
*/
|
||||
public List<TargetProtocolConformanceDescriptor> getTargetProtocolConformanceDescriptors() {
|
||||
return protocolConformanceDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the {@link SwiftTypeMetadata}
|
||||
*
|
||||
|
@ -137,7 +199,7 @@ public class SwiftTypeMetadata {
|
|||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||
while (i + BuiltinTypeDescriptor.SIZE <= block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
BuiltinTypeDescriptor descriptor = new BuiltinTypeDescriptor(reader);
|
||||
|
@ -145,6 +207,7 @@ public class SwiftTypeMetadata {
|
|||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||
i += BuiltinTypeDescriptor.SIZE;
|
||||
i = skipZeroEntries(reader, i, block.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,11 +231,11 @@ public class SwiftTypeMetadata {
|
|||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||
while (i + FieldDescriptor.SIZE <= block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
FieldDescriptor descriptor = new FieldDescriptor(reader);
|
||||
fieldDescriptors.add(descriptor);
|
||||
fieldDescriptors.put(descriptor.getBase(), descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||
List<FieldRecord> records = descriptor.getFieldRecords();
|
||||
|
@ -184,6 +247,7 @@ public class SwiftTypeMetadata {
|
|||
null)));
|
||||
}
|
||||
i += descriptor.getNumFields() * FieldRecord.SIZE;
|
||||
i = skipZeroEntries(reader, i, block.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +271,7 @@ public class SwiftTypeMetadata {
|
|||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||
while (i + AssociatedTypeDescriptor.SIZE <= block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
AssociatedTypeDescriptor descriptor = new AssociatedTypeDescriptor(reader);
|
||||
|
@ -223,6 +287,7 @@ public class SwiftTypeMetadata {
|
|||
blockStart.add(i + j * AssociatedTypeRecord.SIZE), null)));
|
||||
}
|
||||
i += descriptor.getNumAssociatedTypes() * AssociatedTypeRecord.SIZE;
|
||||
i = skipZeroEntries(reader, i, block.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +311,7 @@ public class SwiftTypeMetadata {
|
|||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||
while (i + CaptureDescriptor.SIZE <= block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
CaptureDescriptor descriptor = new CaptureDescriptor(reader);
|
||||
|
@ -271,6 +336,7 @@ public class SwiftTypeMetadata {
|
|||
blockStart.add(i + j * MetadataSourceRecord.SIZE), null)));
|
||||
}
|
||||
i += descriptor.getNumMetadataSources() * MetadataSourceRecord.SIZE;
|
||||
i = skipZeroEntries(reader, i, block.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +360,7 @@ public class SwiftTypeMetadata {
|
|||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = 0;
|
||||
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||
while (i < block.getSize()) {
|
||||
monitor.checkCancelled();
|
||||
MultiPayloadEnumDescriptor descriptor = new MultiPayloadEnumDescriptor(reader);
|
||||
|
@ -302,6 +368,7 @@ public class SwiftTypeMetadata {
|
|||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||
i += MultiPayloadEnumDescriptor.SIZE + descriptor.getContentsSize();
|
||||
i = skipZeroEntries(reader, i, block.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -397,7 +464,7 @@ public class SwiftTypeMetadata {
|
|||
yield null;
|
||||
};
|
||||
if (descriptor != null) {
|
||||
typeDescriptors.add(descriptor);
|
||||
typeDescriptors.put(descriptor.getName(), descriptor);
|
||||
markupList.add(new SwiftStructureInfo(descriptor,
|
||||
new SwiftStructureAddress(addrPair.structAddr(), addrPair.pointerAddr())));
|
||||
}
|
||||
|
@ -409,7 +476,7 @@ public class SwiftTypeMetadata {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parses a table of pointers to {@link SwiftStructure}s found in the given section
|
||||
* Parses a table of pointers to {@link SwiftTypeMetadataStructure}s found in the given section
|
||||
*
|
||||
* @param section The {@link SwiftSection} that contains the pointer table
|
||||
* @param reader A {@link BinaryReader}
|
||||
|
@ -428,14 +495,13 @@ public class SwiftTypeMetadata {
|
|||
reader.setPointerIndex(blockAddr.getOffset() + i);
|
||||
Address pointerAddr = blockAddr.add(i);
|
||||
int offset = reader.readInt(pointerAddr.getOffset());
|
||||
if (offset == 0) {
|
||||
break;
|
||||
}
|
||||
if (offset != 0) {
|
||||
Address structAddr = pointerAddr.add(offset);
|
||||
result.add(new SwiftStructureAddress(structAddr, pointerAddr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log("Failed to parse Swift struction pointers from section '" + section + "'");
|
||||
}
|
||||
|
@ -454,7 +520,7 @@ public class SwiftTypeMetadata {
|
|||
monitor.checkCancelled();
|
||||
monitor.incrementProgress(1);
|
||||
try {
|
||||
SwiftStructure struct = structInfo.struct();
|
||||
SwiftTypeMetadataStructure struct = structInfo.struct();
|
||||
DataType dt = struct.toDataType();
|
||||
DataUtilities.createData(program, structInfo.addr().structAddr(), dt, -1,
|
||||
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
||||
|
@ -465,12 +531,37 @@ public class SwiftTypeMetadata {
|
|||
relativePtrDataType, -1, ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
||||
}
|
||||
}
|
||||
catch (CodeUnitInsertionException | DuplicateNameException | IOException e) {
|
||||
catch (CodeUnitInsertionException e) {
|
||||
// Probably just called more than once
|
||||
}
|
||||
catch (DuplicateNameException | IOException e) {
|
||||
log("Failed to markup: " + structInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads past zeroed out entries in Swift type metadata sections
|
||||
*
|
||||
* @param reader A {@link BinaryReader} positioned within a type metadata section
|
||||
* @param offset The current offset from the start of the type metadata section
|
||||
* @param size The size of the type metadata section (in bytes)
|
||||
* @return The offset from the start of the type metadata section that contains the next
|
||||
* non-zero entry
|
||||
* @throws IOException if an IO-related error occurred
|
||||
*/
|
||||
private int skipZeroEntries(BinaryReader reader, int offset, long size) throws IOException {
|
||||
while (offset + 8 <= size) {
|
||||
long possibleZero = reader.readNextLong();
|
||||
if (possibleZero != 0) {
|
||||
reader.setPointerIndex(reader.getPointerIndex() - 8);
|
||||
return offset;
|
||||
}
|
||||
offset += 8;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to perform logging
|
||||
*
|
||||
|
@ -481,22 +572,24 @@ public class SwiftTypeMetadata {
|
|||
}
|
||||
|
||||
/**
|
||||
* The {@link Address} of a {@link SwiftStructure} and the optional {@link Address} of its
|
||||
* pointer
|
||||
* The {@link Address} of a {@link SwiftTypeMetadataStructure} 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}
|
||||
* @param structAddr The {@link Address} of a {@link SwiftTypeMetadataStructure}
|
||||
* @param pointerAddr The {@link Address} of a pointer to a {@link SwiftTypeMetadataStructure}
|
||||
* (could be null if there is no associated pointer}
|
||||
*/
|
||||
private record SwiftStructureAddress(Address structAddr, Address pointerAddr) {}
|
||||
|
||||
/**
|
||||
* Information about a {@link SwiftStructure}
|
||||
* Information about a {@link SwiftTypeMetadataStructure}
|
||||
*
|
||||
* @param struct The {@link SwiftStructure}
|
||||
* @param addr The {@link SwiftStructureAddress address} of the {@link SwiftStructure}
|
||||
* @param struct The {@link SwiftTypeMetadataStructure}
|
||||
* @param addr The {@link SwiftStructureAddress address} of the
|
||||
* {@link SwiftTypeMetadataStructure}
|
||||
*/
|
||||
private record SwiftStructureInfo(SwiftStructure struct, SwiftStructureAddress addr) {
|
||||
private record SwiftStructureInfo(SwiftTypeMetadataStructure struct,
|
||||
SwiftStructureAddress addr) {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* ###
|
||||
* 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 type metadata structures
|
||||
*/
|
||||
public abstract class SwiftTypeMetadataStructure implements StructConverter {
|
||||
|
||||
public static final String DATA_TYPE_CATEGORY = "/SwiftTypeMetadata";
|
||||
|
||||
private long base;
|
||||
|
||||
public SwiftTypeMetadataStructure(long base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base "address" of this {@link SwiftTypeMetadataStructure}
|
||||
*
|
||||
* @return The base "address" of this {@link SwiftTypeMetadataStructure}
|
||||
*/
|
||||
public long getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the {@link SwiftTypeMetadataStructure}
|
||||
*
|
||||
* @return The name of the {@link SwiftTypeMetadataStructure}
|
||||
*/
|
||||
public abstract String getStructureName();
|
||||
|
||||
/**
|
||||
* Gets a short description of the {@link SwiftTypeMetadataStructure}
|
||||
*
|
||||
* @return A short description of the {@link SwiftTypeMetadataStructure}
|
||||
*/
|
||||
public abstract String getDescription();
|
||||
}
|
|
@ -57,6 +57,23 @@ public class SwiftUtils {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given {@List} of section names contains a Swift section name
|
||||
*
|
||||
* @param sectionNames The {@link List} of section names to check
|
||||
* @return True if the given {@List} of section names contains a Swift section name; otherwise,
|
||||
* false
|
||||
*/
|
||||
public static boolean isSwift(List<String> sectionNames) {
|
||||
List<String> prefixes = List.of("__swift", "swift", ".sw5");
|
||||
for (String sectionName : sectionNames) {
|
||||
if (prefixes.stream().anyMatch(prefix -> sectionName.startsWith(prefix))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link List} of {@link MemoryBlock}s that match the given {@link SwiftSection}
|
||||
*
|
||||
|
|
|
@ -20,7 +20,7 @@ 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.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
@ -30,7 +30,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class AssociatedTypeDescriptor extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of an {@link AssociatedTypeDescriptor} structure
|
||||
|
@ -51,6 +51,7 @@ public final class AssociatedTypeDescriptor implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public AssociatedTypeDescriptor(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
conformingTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||
protocolTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||
numAssociatedTypes = reader.readNextInt();
|
||||
|
|
|
@ -18,7 +18,7 @@ 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.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
@ -28,7 +28,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class AssociatedTypeRecord extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of an {@link AssociatedTypeRecord} structure
|
||||
|
@ -45,6 +45,7 @@ public final class AssociatedTypeRecord implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public AssociatedTypeRecord(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
name = reader.readNext(SwiftUtils::relativeString);
|
||||
substitutedTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ 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.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -27,7 +28,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class BuiltinTypeDescriptor extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of a {@link BuiltinTypeDescriptor} structure
|
||||
|
@ -47,6 +48,7 @@ public final class BuiltinTypeDescriptor implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public BuiltinTypeDescriptor(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
typeName = reader.readNext(SwiftUtils::relativeString);
|
||||
size = reader.readNextInt();
|
||||
alignmentAndFlags = reader.readNextInt();
|
||||
|
|
|
@ -20,10 +20,8 @@ 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.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
|
@ -31,7 +29,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class CaptureDescriptor extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of a {@link CaptureDescriptor} structure
|
||||
|
@ -52,6 +50,7 @@ public final class CaptureDescriptor implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public CaptureDescriptor(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
numCaptureTypes = reader.readNextInt();
|
||||
numMetadataSources = reader.readNextInt();
|
||||
numBindings = reader.readNextInt();
|
||||
|
|
|
@ -18,7 +18,8 @@ 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.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -27,7 +28,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class CaptureTypeRecord extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of a {@link CaptureTypeRecord} structure
|
||||
|
@ -43,6 +44,7 @@ public final class CaptureTypeRecord implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public CaptureTypeRecord(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ 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.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
@ -26,7 +26,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
/**
|
||||
* Represents a Swift entry point
|
||||
*/
|
||||
public final class EntryPoint implements SwiftStructure {
|
||||
public final class EntryPoint extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of an {@link EntryPoint} structure
|
||||
|
@ -42,6 +42,7 @@ public final class EntryPoint implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public EntryPoint(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
entryPoint = reader.readNextInt();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.swift.*;
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -29,7 +30,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class FieldDescriptor extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of a {@link FieldDescriptor} structure
|
||||
|
@ -51,6 +52,7 @@ public final class FieldDescriptor implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public FieldDescriptor(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||
superclass = reader.readNextInt();
|
||||
kind = reader.readNextUnsignedShort();
|
||||
|
|
|
@ -18,7 +18,8 @@ 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.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -27,7 +28,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class FieldRecord extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of a {@link FieldRecord} structure
|
||||
|
@ -45,6 +46,7 @@ public final class FieldRecord implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public FieldRecord(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
flags = reader.readNextInt();
|
||||
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||
fieldName = reader.readNext(SwiftUtils::relativeString);
|
||||
|
|
|
@ -18,7 +18,8 @@ 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.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -27,7 +28,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class MetadataSourceRecord extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of a {@link MetadataSourceRecord} structure
|
||||
|
@ -44,6 +45,7 @@ public final class MetadataSourceRecord implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public MetadataSourceRecord(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||
mangledMetadataSource = reader.readNext(SwiftUtils::relativeString);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ 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.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
@ -28,7 +28,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class MultiPayloadEnumDescriptor extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of a {@link MultiPayloadEnumDescriptor} structure. This size does not
|
||||
|
@ -48,6 +48,7 @@ public final class MultiPayloadEnumDescriptor implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public MultiPayloadEnumDescriptor(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
typeName = reader.readNext(SwiftUtils::relativeString);
|
||||
int size = (reader.readNextInt() >> 16) & 0xffff;
|
||||
reader.setPointerIndex(reader.getPointerIndex() - 4);
|
||||
|
|
|
@ -19,9 +19,7 @@ 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.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,7 +18,8 @@ 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.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -27,7 +28,12 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public class TargetContextDescriptor extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of a {@link TargetContextDescriptor} structure
|
||||
*/
|
||||
public static final int SIZE = 8;
|
||||
|
||||
private int flags;
|
||||
private int parent;
|
||||
|
@ -39,6 +45,7 @@ public class TargetContextDescriptor implements SwiftStructure {
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public TargetContextDescriptor(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
flags = reader.readNextInt();
|
||||
parent = reader.readNextInt();
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ 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.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -27,7 +28,7 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*
|
||||
* @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 {
|
||||
public final class TargetProtocolConformanceDescriptor extends SwiftTypeMetadataStructure {
|
||||
|
||||
private int protocolDescriptor;
|
||||
private int nominalTypeDescriptor;
|
||||
|
@ -41,6 +42,7 @@ public final class TargetProtocolConformanceDescriptor implements SwiftStructure
|
|||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public TargetProtocolConformanceDescriptor(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
protocolDescriptor = reader.readNextInt();
|
||||
nominalTypeDescriptor = reader.readNextInt();
|
||||
protocolWitnessTable = reader.readNextInt();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package ghidra.app.util.bin.format.swift.types;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
|
@ -73,6 +74,20 @@ public class TargetTypeContextDescriptor extends TargetContextDescriptor {
|
|||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this {@link TargetTypeContextDescriptor}'s {@link FieldDescriptor}
|
||||
*
|
||||
* @param fieldDescriptors A {@link Map} of {@link FieldDescriptor}'s keyed by their base
|
||||
* addresses
|
||||
* @return This {@link TargetTypeContextDescriptor}'s {@link FieldDescriptor}, or null if it
|
||||
* doesn't have one
|
||||
*/
|
||||
public FieldDescriptor getFieldDescriptor(Map<Long, FieldDescriptor> fieldDescriptors) {
|
||||
FieldDescriptor fieldDescriptor =
|
||||
fieldDescriptors.get(getBase() + TargetContextDescriptor.SIZE + 8 + fields);
|
||||
return fieldDescriptor != null ? fieldDescriptor : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStructureName() {
|
||||
return getMyStructureName();
|
||||
|
|
|
@ -73,6 +73,7 @@ public class DemangledDataType extends DemangledType {
|
|||
public final static String LONG = "long";
|
||||
public final static String LONG_LONG = "long long";
|
||||
public final static String FLOAT = "float";
|
||||
public final static String FLOAT2 = "float2";
|
||||
public final static String DOUBLE = "double";
|
||||
public final static String INT8 = "__int8";
|
||||
public final static String INT16 = "__int16";
|
||||
|
@ -94,7 +95,7 @@ public class DemangledDataType extends DemangledType {
|
|||
|
||||
public final static String[] PRIMITIVES =
|
||||
{ VOID, BOOL, CHAR, WCHAR_T, WCHAR16, WCHAR32, SHORT, INT, INT0_T, LONG,
|
||||
LONG_LONG, FLOAT, DOUBLE, INT128, FLOAT128, LONG_DOUBLE, };
|
||||
LONG_LONG, FLOAT, FLOAT2, DOUBLE, INT128, FLOAT128, LONG_DOUBLE, };
|
||||
|
||||
private int arrayDimensions = 0;
|
||||
private boolean isClass;
|
||||
|
@ -293,6 +294,9 @@ public class DemangledDataType extends DemangledType {
|
|||
else if (FLOAT.equals(name)) {
|
||||
dt = FloatDataType.dataType;
|
||||
}
|
||||
else if (FLOAT2.equals(name)) {
|
||||
dt = Float2DataType.dataType;
|
||||
}
|
||||
else if (FLOAT128.equals(name)) {
|
||||
dt = new TypedefDataType(FLOAT128, Float16DataType.dataType);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class DemangledFunction extends DemangledObject {
|
|||
protected DemangledDataType returnType;
|
||||
protected String callingConvention;// __cdecl, __thiscall, etc.
|
||||
protected boolean thisPassedOnStack = true;
|
||||
protected List<DemangledDataType> parameters = new ArrayList<>();
|
||||
protected List<DemangledParameter> parameters = new ArrayList<>();
|
||||
protected DemangledTemplate template;
|
||||
protected boolean isOverloadedOperator = false;
|
||||
protected SourceType signatureSourceType = SourceType.ANALYSIS;
|
||||
|
@ -140,11 +140,15 @@ public class DemangledFunction extends DemangledObject {
|
|||
this.isOverloadedOperator = isOverloadedOperator;
|
||||
}
|
||||
|
||||
public void addParameter(DemangledDataType parameter) {
|
||||
public void addParameter(DemangledParameter parameter) {
|
||||
parameters.add(parameter);
|
||||
}
|
||||
|
||||
public List<DemangledDataType> getParameters() {
|
||||
public void addParameters(List<DemangledParameter> params) {
|
||||
parameters.addAll(params);
|
||||
}
|
||||
|
||||
public List<DemangledParameter> getParameters() {
|
||||
return new ArrayList<>(parameters);
|
||||
}
|
||||
|
||||
|
@ -323,7 +327,7 @@ public class DemangledFunction extends DemangledObject {
|
|||
}
|
||||
|
||||
protected void addParameters(StringBuilder buffer, boolean format) {
|
||||
Iterator<DemangledDataType> paramIterator = parameters.iterator();
|
||||
Iterator<DemangledParameter> paramIterator = parameters.iterator();
|
||||
buffer.append('(');
|
||||
int padLength = format ? buffer.length() : 0;
|
||||
String pad = StringUtils.rightPad("", padLength);
|
||||
|
@ -332,7 +336,11 @@ public class DemangledFunction extends DemangledObject {
|
|||
}
|
||||
|
||||
while (paramIterator.hasNext()) {
|
||||
buffer.append(paramIterator.next().getSignature());
|
||||
DemangledParameter param = paramIterator.next();
|
||||
buffer.append(param.getType().getSignature());
|
||||
if (param.getLabel() != null) {
|
||||
buffer.append(" " + param.getLabel());
|
||||
}
|
||||
if (paramIterator.hasNext()) {
|
||||
buffer.append(',');
|
||||
if (format) {
|
||||
|
@ -353,9 +361,9 @@ public class DemangledFunction extends DemangledObject {
|
|||
public String getParameterString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append('(');
|
||||
Iterator<DemangledDataType> dditer = parameters.iterator();
|
||||
Iterator<DemangledParameter> dditer = parameters.iterator();
|
||||
while (dditer.hasNext()) {
|
||||
buffer.append(dditer.next().getSignature());
|
||||
buffer.append(dditer.next().getType().getSignature());
|
||||
if (dditer.hasNext()) {
|
||||
buffer.append(',');
|
||||
}
|
||||
|
@ -576,13 +584,13 @@ public class DemangledFunction extends DemangledObject {
|
|||
return false;
|
||||
}
|
||||
|
||||
DemangledDataType lastType = parameters.get(parameters.size() - 1);
|
||||
DemangledDataType lastType = parameters.get(parameters.size() - 1).getType();
|
||||
return lastType.isVarArgs();
|
||||
}
|
||||
|
||||
private boolean hasVoidParams() {
|
||||
if (parameters.size() == 1) {
|
||||
DemangledDataType ddt = parameters.get(0);
|
||||
DemangledDataType ddt = parameters.get(0).getType();
|
||||
return ddt.isVoid() && !ddt.isPointer();
|
||||
}
|
||||
return false;
|
||||
|
@ -634,7 +642,7 @@ public class DemangledFunction extends DemangledObject {
|
|||
// If returnType is null check for constructor or destructor names
|
||||
if (THIS_CALL.equals(function.getCallingConventionName())) {
|
||||
String n = getName();
|
||||
if (n.equals(namespace.getName())) {
|
||||
if (namespace != null && n.equals(namespace.getName())) {
|
||||
// constructor
|
||||
return DataType.DEFAULT;
|
||||
}
|
||||
|
@ -698,17 +706,18 @@ public class DemangledFunction extends DemangledObject {
|
|||
private List<ParameterDefinitionImpl> convertMangledToParamDef(Program program) {
|
||||
|
||||
List<ParameterDefinitionImpl> args = new ArrayList<>();
|
||||
for (DemangledDataType param : parameters) {
|
||||
for (DemangledParameter param : parameters) {
|
||||
// stop when a void parameter is hit. This probably the only defined parameter.
|
||||
if (param.isVoid() && !param.isPointer()) {
|
||||
DemangledDataType type = param.getType();
|
||||
if (type.isVoid() && !type.isPointer()) {
|
||||
break;
|
||||
}
|
||||
if (param.isVarArgs()) {
|
||||
if (type.isVarArgs()) {
|
||||
break;
|
||||
}
|
||||
|
||||
DataType dt = param.getDataType(program.getDataTypeManager());
|
||||
args.add(new ParameterDefinitionImpl(null, dt, null));
|
||||
DataType dt = type.getDataType(program.getDataTypeManager());
|
||||
args.add(new ParameterDefinitionImpl(param.getLabel(), dt, null));
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/* ###
|
||||
* 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.demangler;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A class to represent a {@link DemangledObject} that should get represented as a Ghidra label
|
||||
*/
|
||||
public class DemangledLabel extends DemangledObject {
|
||||
|
||||
/**
|
||||
* Creates a new {@link DemangledLabel}
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
* @param name The label name
|
||||
*/
|
||||
public DemangledLabel(String mangled, String originalDemangled, String name) {
|
||||
super(mangled, originalDemangled);
|
||||
setName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyTo(Program program, Address address, DemanglerOptions options,
|
||||
TaskMonitor monitor) throws Exception {
|
||||
Symbol symbol = applyDemangledName(address, true, false, program);
|
||||
return symbol != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature(boolean format) {
|
||||
return originalDemangled;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/* ###
|
||||
* 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.demangler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An convenience {@link Demangled} object that holds a {@link List} of other
|
||||
* {@link Demangled} objects
|
||||
*/
|
||||
public class DemangledList extends ArrayList<Demangled> implements Demangled {
|
||||
|
||||
/**
|
||||
* Creates a {@link DemangledList} and adds the given {@link List} to it
|
||||
*
|
||||
* @param demangledList The {@link List} of {@link Demangled} objects to add
|
||||
*/
|
||||
public DemangledList(List<Demangled> demangledList) {
|
||||
super(demangledList);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return true if this contains any <code>null</code> elements; otherwise, false}
|
||||
*/
|
||||
public boolean containsNull() {
|
||||
return stream().anyMatch(e -> e == null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMangledString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalDemangled() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDemangledName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Demangled getNamespace() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNamespace(Demangled ns) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespaceString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespaceName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.demangler;
|
||||
|
||||
/**
|
||||
* A class to represent a demangled function parameter.
|
||||
* <p>
|
||||
* This extends {@link DemangledDataType} in order to associate an optional parameter label with
|
||||
* its data type.
|
||||
*/
|
||||
public class DemangledParameter {
|
||||
|
||||
private DemangledDataType type;
|
||||
private String label;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DemangledParameter} with the given type and no label
|
||||
*
|
||||
* @param type The parameter type
|
||||
*/
|
||||
public DemangledParameter(DemangledDataType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the parameter's type}
|
||||
*/
|
||||
public DemangledDataType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the parameter's label (could be null)}
|
||||
*/
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameter's label
|
||||
*
|
||||
* @param label The label (null for no label)
|
||||
*/
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String ret = type.toString();
|
||||
if (label != null) {
|
||||
ret += " " + label;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/* ###
|
||||
* 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.demangler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.data.*;
|
||||
|
||||
/**
|
||||
* A class to represent a demangled structure
|
||||
*/
|
||||
public class DemangledStructure extends DemangledDataType {
|
||||
|
||||
/**
|
||||
* A field of a {@link DemangledStructure}
|
||||
*
|
||||
* @param name The field name
|
||||
* @param description The field description
|
||||
* @param type The field {@link DemangledDataType type}
|
||||
*/
|
||||
public record Field(String name, String description, DemangledDataType type) {}
|
||||
|
||||
private List<Field> fields = new ArrayList<>();
|
||||
private String categoryPath;
|
||||
private boolean packed;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DemangledStructure}
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
* @param name The structure name
|
||||
* @param categoryPath The structure category path
|
||||
* @param packed True if the structure should be packed; otherwise, false
|
||||
*/
|
||||
public DemangledStructure(String mangled, String originalDemangled, String name,
|
||||
String categoryPath, boolean packed) {
|
||||
super(mangled, originalDemangled, name);
|
||||
setStruct();
|
||||
this.categoryPath = categoryPath;
|
||||
this.packed = packed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new field to the structure. The field will not have a description.
|
||||
*
|
||||
* @param name The field name
|
||||
* @param type The field {@link DemangledDataType type}
|
||||
*/
|
||||
public void addField(String name, DemangledDataType type) {
|
||||
fields.add(new Field(name, null, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new field to the structure
|
||||
*
|
||||
* @param name The field name
|
||||
* @param description The field description
|
||||
* @param type The field {@link DemangledDataType type}
|
||||
*/
|
||||
public void addField(String name, String description, DemangledDataType type) {
|
||||
fields.add(new Field(name, description, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link List} of {@link Field}s
|
||||
*
|
||||
* @return The {@link List} of {@link Field}s
|
||||
*/
|
||||
public List<Field> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(DataTypeManager dataTypeManager) {
|
||||
String name = getName();
|
||||
if (name == null) {
|
||||
return DataType.DEFAULT;
|
||||
}
|
||||
|
||||
StructureDataType struct = new StructureDataType(name, 0, dataTypeManager);
|
||||
for (Field field : fields) {
|
||||
struct.add(field.type().getDataType(dataTypeManager), field.name(),
|
||||
field.description());
|
||||
}
|
||||
struct.setPackingEnabled(packed);
|
||||
struct.setCategoryPath(new CategoryPath(categoryPath));
|
||||
return struct;
|
||||
}
|
||||
|
||||
}
|
|
@ -24,6 +24,7 @@ import ghidra.app.util.Option;
|
|||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.bin.ByteProviderWrapper;
|
||||
import ghidra.app.util.bin.format.macho.*;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.app.util.bin.format.ubi.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.formats.gfilesystem.*;
|
||||
|
@ -60,7 +61,13 @@ public class MachoLoader extends AbstractLibrarySupportLoader {
|
|||
MachHeader machHeader = new MachHeader(provider);
|
||||
String magic =
|
||||
CpuTypes.getMagicString(machHeader.getCpuType(), machHeader.getCpuSubType());
|
||||
List<QueryResult> results = QueryOpinionService.query(MACH_O_NAME, magic, null);
|
||||
List<String> sectionNames = machHeader.parseSegments()
|
||||
.stream()
|
||||
.flatMap(seg -> seg.getSections().stream())
|
||||
.map(section -> section.getSectionName())
|
||||
.toList();
|
||||
String compiler = SwiftUtils.isSwift(sectionNames) ? "swift" : null;
|
||||
List<QueryResult> results = QueryOpinionService.query(MACH_O_NAME, magic, compiler);
|
||||
for (QueryResult result : results) {
|
||||
loadSpecs.add(new LoadSpec(this, machHeader.getImageBase(), result));
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import ghidra.app.util.bin.format.pe.ImageCor20Header.ImageCor20Flags;
|
|||
import ghidra.app.util.bin.format.pe.PortableExecutable.SectionLayout;
|
||||
import ghidra.app.util.bin.format.pe.debug.DebugCOFFSymbol;
|
||||
import ghidra.app.util.bin.format.pe.debug.DebugDirectoryParser;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.framework.options.Options;
|
||||
|
@ -904,6 +905,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
CLI("cli", "cli"),
|
||||
Rustc(RustConstants.RUST_COMPILER, RustConstants.RUST_COMPILER),
|
||||
GOLANG("golang", "golang"),
|
||||
Swift("swift", "swift"),
|
||||
Unknown("unknown", "unknown"),
|
||||
|
||||
// The following values represent the presence of ambiguous indicators
|
||||
|
@ -970,6 +972,15 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
return CompilerEnum.Rustc;
|
||||
}
|
||||
|
||||
// Check for Swift
|
||||
List<String> sectionNames =
|
||||
Arrays.stream(pe.getNTHeader().getFileHeader().getSectionHeaders())
|
||||
.map(section -> section.getName())
|
||||
.toList();
|
||||
if (SwiftUtils.isSwift(sectionNames)) {
|
||||
return CompilerEnum.Swift;
|
||||
}
|
||||
|
||||
// Check for managed code (.NET)
|
||||
if (pe.getNTHeader().getOptionalHeader().isCLI()) {
|
||||
return CompilerEnum.CLI;
|
||||
|
|
|
@ -485,7 +485,7 @@ public class GnuDemanglerParser {
|
|||
//
|
||||
setNameAndNamespace(function, simpleName);
|
||||
|
||||
for (DemangledDataType parameter : signatureParts.getParameters()) {
|
||||
for (DemangledParameter parameter : signatureParts.getParameters()) {
|
||||
function.addParameter(parameter);
|
||||
}
|
||||
|
||||
|
@ -630,9 +630,9 @@ public class GnuDemanglerParser {
|
|||
* Reason being, you need to take into account nested templates
|
||||
* and function pointers.
|
||||
*/
|
||||
private List<DemangledDataType> parseParameters(String parameterString) {
|
||||
private List<DemangledParameter> parseParameters(String parameterString) {
|
||||
List<String> parameterStrings = tokenizeParameters(parameterString);
|
||||
List<DemangledDataType> parameters = convertIntoParameters(parameterStrings);
|
||||
List<DemangledParameter> parameters = convertIntoParameters(parameterStrings);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
@ -735,12 +735,12 @@ public class GnuDemanglerParser {
|
|||
* This method converts each parameter string into
|
||||
* actual DemangledDataType objects.
|
||||
*/
|
||||
private List<DemangledDataType> convertIntoParameters(List<String> parameterStrings) {
|
||||
List<DemangledDataType> parameters = new ArrayList<>();
|
||||
private List<DemangledParameter> convertIntoParameters(List<String> parameterStrings) {
|
||||
List<DemangledParameter> parameters = new ArrayList<>();
|
||||
|
||||
for (String parameter : parameterStrings) {
|
||||
DemangledDataType dt = parseParameter(parameter);
|
||||
parameters.add(dt);
|
||||
parameters.add(new DemangledParameter(dt));
|
||||
}
|
||||
|
||||
return parameters;
|
||||
|
@ -1311,10 +1311,10 @@ public class GnuDemanglerParser {
|
|||
contents = string.substring(1, string.length() - 1);
|
||||
}
|
||||
|
||||
List<DemangledDataType> parameters = parseParameters(contents);
|
||||
List<DemangledParameter> parameters = parseParameters(contents);
|
||||
DemangledTemplate template = new DemangledTemplate();
|
||||
for (DemangledDataType parameter : parameters) {
|
||||
template.addParameter(parameter);
|
||||
for (DemangledParameter parameter : parameters) {
|
||||
template.addParameter(parameter.getType());
|
||||
}
|
||||
return template;
|
||||
}
|
||||
|
@ -1399,16 +1399,16 @@ public class GnuDemanglerParser {
|
|||
return dfp;
|
||||
}
|
||||
|
||||
private DemangledFunctionPointer createFunctionPointer(String paramerterString,
|
||||
private DemangledFunctionPointer createFunctionPointer(String parameterString,
|
||||
String returnType) {
|
||||
|
||||
List<DemangledDataType> parameters = parseParameters(paramerterString);
|
||||
List<DemangledParameter> parameters = parseParameters(parameterString);
|
||||
|
||||
DemangledFunctionPointer dfp = new DemangledFunctionPointer(mangledSource, demangledSource);
|
||||
DemangledDataType returnDataType = parseReturnType(returnType);
|
||||
dfp.setReturnType(returnDataType);
|
||||
for (DemangledDataType parameter : parameters) {
|
||||
dfp.addParameter(parameter);
|
||||
for (DemangledParameter parameter : parameters) {
|
||||
dfp.addParameter(parameter.getType());
|
||||
}
|
||||
return dfp;
|
||||
}
|
||||
|
@ -1889,8 +1889,8 @@ public class GnuDemanglerParser {
|
|||
// operator itself could be in a class namespace
|
||||
setNameAndNamespace(function, operatorText);
|
||||
|
||||
List<DemangledDataType> parameters = parseParameters(parametersText);
|
||||
for (DemangledDataType parameter : parameters) {
|
||||
List<DemangledParameter> parameters = parseParameters(parametersText);
|
||||
for (DemangledParameter parameter : parameters) {
|
||||
function.addParameter(parameter);
|
||||
}
|
||||
|
||||
|
@ -2029,7 +2029,7 @@ public class GnuDemanglerParser {
|
|||
private String name;
|
||||
private String rawParameterPrefix;
|
||||
|
||||
private List<DemangledDataType> parameters;
|
||||
private List<DemangledParameter> parameters;
|
||||
|
||||
FunctionSignatureParts(String signatureString) {
|
||||
|
||||
|
@ -2077,7 +2077,7 @@ public class GnuDemanglerParser {
|
|||
return isFunction;
|
||||
}
|
||||
|
||||
List<DemangledDataType> getParameters() {
|
||||
List<DemangledParameter> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,9 +54,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
assertName(object, "bob");
|
||||
|
||||
DemangledFunction function = (DemangledFunction) object;
|
||||
List<DemangledDataType> parameters = function.getParameters();
|
||||
List<DemangledParameter> parameters = function.getParameters();
|
||||
assertEquals(1, parameters.size());
|
||||
DemangledDataType p1 = parameters.get(0);
|
||||
DemangledDataType p1 = parameters.get(0).getType();
|
||||
assertEquals("bob(int const[8] (*) [12])", p1.getOriginalDemangled());
|
||||
assertEquals("undefined bob(int const *[])", object.getSignature(false));
|
||||
}
|
||||
|
@ -113,9 +113,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
DemangledObject object = parser.parse("fake", "Layout::graphNew(short[][][][], char*)");
|
||||
assertType(object, DemangledFunction.class);
|
||||
DemangledFunction function = (DemangledFunction) object;
|
||||
List<DemangledDataType> parameters = function.getParameters();
|
||||
List<DemangledParameter> parameters = function.getParameters();
|
||||
assertEquals(2, parameters.size());
|
||||
DemangledDataType p1 = parameters.get(0);
|
||||
DemangledDataType p1 = parameters.get(0).getType();
|
||||
assertEquals(4, p1.getArrayDimensions());
|
||||
}
|
||||
|
||||
|
@ -153,12 +153,12 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
|
||||
DemangledFunction method = (DemangledFunction) object;
|
||||
|
||||
List<DemangledDataType> parameters = method.getParameters();
|
||||
List<DemangledParameter> parameters = method.getParameters();
|
||||
assertEquals(4, parameters.size());
|
||||
assertEquals("unsigned long (*)(long const &)", parameters.get(0).getSignature());
|
||||
assertEquals("unsigned long", parameters.get(1).getSignature());
|
||||
assertEquals("unsigned long", parameters.get(2).getSignature());
|
||||
assertEquals("float", parameters.get(3).getSignature());
|
||||
assertEquals("unsigned long (*)(long const &)", parameters.get(0).getType().getSignature());
|
||||
assertEquals("unsigned long", parameters.get(1).getType().getSignature());
|
||||
assertEquals("unsigned long", parameters.get(2).getType().getSignature());
|
||||
assertEquals("float", parameters.get(3).getType().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -176,9 +176,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
"_Rb_tree<Location,Location,std::_Identity<Location>,std::less<Location>,std::allocator<Location>>");
|
||||
|
||||
DemangledFunction function = (DemangledFunction) object;
|
||||
List<DemangledDataType> parameters = function.getParameters();
|
||||
List<DemangledParameter> parameters = function.getParameters();
|
||||
assertEquals(1, parameters.size());
|
||||
assertEquals("Location const &", parameters.get(0).getSignature());
|
||||
assertEquals("Location const &", parameters.get(0).getType().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -194,7 +194,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
assertType(object, DemangledFunction.class);
|
||||
|
||||
DemangledFunction function = (DemangledFunction) object;
|
||||
List<DemangledDataType> parameters = function.getParameters();
|
||||
List<DemangledParameter> parameters = function.getParameters();
|
||||
|
||||
assertEquals(
|
||||
"__insertion_sort<__gnu_cxx::__normal_iterator<std::pair<unsigned_long,PcodeOp*>*,std::vector<std::pair<unsigned_long,PcodeOp*>,std::allocator<std::pair<unsigned_long,PcodeOp*>>>>,bool(*)(std::pair<unsigned_long,PcodeOp*>const&,std::pair<unsigned_long,PcodeOp*>const&)>",
|
||||
|
@ -211,9 +211,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
"bool (*)(std::pair<unsigned long,PcodeOp *> const &,std::pair<unsigned long,PcodeOp *> const &)",
|
||||
parameters.get(2).toString());
|
||||
|
||||
assertType(parameters.get(2), DemangledFunctionPointer.class);
|
||||
assertType(parameters.get(2).getType(), DemangledFunctionPointer.class);
|
||||
|
||||
DemangledFunctionPointer fptr = (DemangledFunctionPointer) parameters.get(2);
|
||||
DemangledFunctionPointer fptr = (DemangledFunctionPointer) parameters.get(2).getType();
|
||||
|
||||
assertEquals("bool", fptr.getReturnType().getName());
|
||||
|
||||
|
@ -234,9 +234,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
assertEquals(
|
||||
"undefined std::set<bbnode*,std::less<bbnode*>,std::allocator<bbnode*>>::insert(bbnode const * &)",
|
||||
method.getSignature(false));
|
||||
List<DemangledDataType> parameters = method.getParameters();
|
||||
List<DemangledParameter> parameters = method.getParameters();
|
||||
assertEquals(1, parameters.size());
|
||||
assertEquals("bbnode const * &", parameters.get(0).getSignature());
|
||||
assertEquals("bbnode const * &", parameters.get(0).getType().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -252,9 +252,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
DemangledFunction method = (DemangledFunction) object;
|
||||
assertEquals("undefined Bar::Fred::Fred(int)", method.getSignature(false));
|
||||
|
||||
List<DemangledDataType> parameters = method.getParameters();
|
||||
List<DemangledParameter> parameters = method.getParameters();
|
||||
assertEquals(1, parameters.size());
|
||||
assertEquals("int", parameters.get(0).getSignature());
|
||||
assertEquals("int", parameters.get(0).getType().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -428,9 +428,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
DemangledFunction function = (DemangledFunction) object;
|
||||
assertEquals("undefined Foo::getBool(float)", function.getSignature(false));
|
||||
|
||||
List<DemangledDataType> parameters = function.getParameters();
|
||||
List<DemangledParameter> parameters = function.getParameters();
|
||||
assertEquals(1, parameters.size());
|
||||
assertEquals("float", parameters.get(0).getSignature());
|
||||
assertEquals("float", parameters.get(0).getType().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -447,13 +447,13 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
|
||||
DemangledFunction function = (DemangledFunction) object;
|
||||
|
||||
List<DemangledDataType> parameters = function.getParameters();
|
||||
List<DemangledParameter> parameters = function.getParameters();
|
||||
assertEquals(5, parameters.size());
|
||||
assertEquals("int", parameters.get(0).getSignature());
|
||||
assertEquals("double", parameters.get(1).getSignature());
|
||||
assertEquals("char", parameters.get(2).getSignature());
|
||||
assertEquals("long", parameters.get(3).getSignature());
|
||||
assertEquals("short", parameters.get(4).getSignature());
|
||||
assertEquals("int", parameters.get(0).getType().getSignature());
|
||||
assertEquals("double", parameters.get(1).getType().getSignature());
|
||||
assertEquals("char", parameters.get(2).getType().getSignature());
|
||||
assertEquals("long", parameters.get(3).getType().getSignature());
|
||||
assertEquals("short", parameters.get(4).getType().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -827,13 +827,13 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
|
||||
DemangledFunction method = (DemangledFunction) object;
|
||||
|
||||
List<DemangledDataType> parameters = method.getParameters();
|
||||
List<DemangledParameter> parameters = method.getParameters();
|
||||
assertEquals(5, parameters.size());
|
||||
assertEquals("SECTION_INFO *", parameters.get(0).getSignature());
|
||||
assertEquals("int *", parameters.get(1).getSignature());
|
||||
assertEquals("int *[]", parameters.get(2).getSignature());
|
||||
assertEquals("int", parameters.get(3).getSignature());
|
||||
assertEquals("short const *", parameters.get(4).getSignature());
|
||||
assertEquals("SECTION_INFO *", parameters.get(0).getType().getSignature());
|
||||
assertEquals("int *", parameters.get(1).getType().getSignature());
|
||||
assertEquals("int *[]", parameters.get(2).getType().getSignature());
|
||||
assertEquals("int", parameters.get(3).getType().getSignature());
|
||||
assertEquals("short const *", parameters.get(4).getType().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -935,10 +935,10 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
"undefined Magick::operator<(Magick::Coordinate const &,Magick::Coordinate const &)",
|
||||
method.getSignature(false));
|
||||
|
||||
List<DemangledDataType> parameters = method.getParameters();
|
||||
List<DemangledParameter> parameters = method.getParameters();
|
||||
assertEquals(2, parameters.size());
|
||||
assertEquals("Magick::Coordinate const &", parameters.get(0).getSignature());
|
||||
assertEquals("Magick::Coordinate const &", parameters.get(1).getSignature());
|
||||
assertEquals("Magick::Coordinate const &", parameters.get(0).getType().getSignature());
|
||||
assertEquals("Magick::Coordinate const &", parameters.get(1).getType().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1072,9 +1072,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
assertEquals("undefined Magick::pageImage::operator()(Magick::Image &)",
|
||||
method.getSignature(false));
|
||||
|
||||
List<DemangledDataType> parameters = method.getParameters();
|
||||
List<DemangledParameter> parameters = method.getParameters();
|
||||
assertEquals(1, parameters.size());
|
||||
assertEquals("Magick::Image &", parameters.get(0).getSignature());
|
||||
assertEquals("Magick::Image &", parameters.get(0).getType().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1536,13 +1536,14 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
|
||||
DemangledFunction df = (DemangledFunction) object;
|
||||
|
||||
List<DemangledDataType> parameters = df.getParameters();
|
||||
List<DemangledParameter> parameters = df.getParameters();
|
||||
assertEquals("Number of parameters", 1, parameters.size());
|
||||
assertEquals("Name of type parsed", "F", parameters.get(0).getName());
|
||||
assertEquals("Param Type Name parsed", "WTF", parameters.get(0).getNamespace().toString());
|
||||
assertEquals("Name of type parsed", "F", parameters.get(0).getType().getName());
|
||||
assertEquals("Param Type Name parsed", "WTF",
|
||||
parameters.get(0).getType().getNamespace().toString());
|
||||
assertEquals("Param Template was parsed",
|
||||
"<WTF::F<void (Core::FileClient &)> (Core::File &)>",
|
||||
parameters.get(0).getTemplate().toString());
|
||||
parameters.get(0).getType().getTemplate().toString());
|
||||
|
||||
assertEquals(
|
||||
"undefined Core::AsyncFile::perform(WTF::F<WTF::F<void (Core::FileClient &)> (Core::File &)> &&)",
|
||||
|
@ -1569,9 +1570,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
|
||||
DemangledFunction df = (DemangledFunction) object;
|
||||
|
||||
List<DemangledDataType> parameters = df.getParameters();
|
||||
List<DemangledParameter> parameters = df.getParameters();
|
||||
assertEquals("Number of parameters", 1, parameters.size());
|
||||
DemangledDataType demangParamDT = parameters.get(0);
|
||||
DemangledDataType demangParamDT = parameters.get(0).getType();
|
||||
|
||||
assertEquals("Name of type parsed", "function", demangParamDT.getName());
|
||||
assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString());
|
||||
|
@ -1601,9 +1602,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
|
||||
DemangledFunction df = (DemangledFunction) object;
|
||||
|
||||
List<DemangledDataType> parameters = df.getParameters();
|
||||
List<DemangledParameter> parameters = df.getParameters();
|
||||
assertEquals("Number of parameters", 1, parameters.size());
|
||||
DemangledDataType demangParamDT = parameters.get(0);
|
||||
DemangledDataType demangParamDT = parameters.get(0).getType();
|
||||
|
||||
assertEquals("Name of type parsed", "function", demangParamDT.getName());
|
||||
assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString());
|
||||
|
@ -1705,9 +1706,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
|||
assertType(object, DemangledFunction.class);
|
||||
|
||||
DemangledFunction function = (DemangledFunction) object;
|
||||
List<DemangledDataType> parameters = function.getParameters();
|
||||
List<DemangledParameter> parameters = function.getParameters();
|
||||
assertEquals(2, parameters.size());
|
||||
assertTrue(parameters.get(1).isVarArgs());
|
||||
assertTrue(parameters.get(1).getType().isVarArgs());
|
||||
|
||||
assertEquals("undefined testVarArgs(int,...)", object.getSignature(false));
|
||||
}
|
||||
|
|
|
@ -369,7 +369,8 @@ public class MDMangGhidra extends MDMang {
|
|||
MDArgumentsList args = functionType.getArgumentsList();
|
||||
if (functionType.hasArgs() && args != null) {
|
||||
for (int index = 0; index < args.getNumArgs(); index++) {
|
||||
function.addParameter(processDataType(null, args.getArg(index)));
|
||||
function.addParameter(
|
||||
new DemangledParameter(processDataType(null, args.getArg(index))));
|
||||
}
|
||||
}
|
||||
if (functionType.isTypeCast()) {
|
||||
|
|
0
Ghidra/Features/SwiftDemangler/Module.manifest
Normal file
0
Ghidra/Features/SwiftDemangler/Module.manifest
Normal file
26
Ghidra/Features/SwiftDemangler/build.gradle
Normal file
26
Ghidra/Features/SwiftDemangler/build.gradle
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/javaProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
eclipse.project.name = 'Features SwiftDemangler'
|
||||
|
||||
dependencies {
|
||||
api project(":Base")
|
||||
}
|
2
Ghidra/Features/SwiftDemangler/certification.manifest
Normal file
2
Ghidra/Features/SwiftDemangler/certification.manifest
Normal file
|
@ -0,0 +1,2 @@
|
|||
##VERSION: 2.0
|
||||
Module.manifest||GHIDRA||||END|
|
|
@ -0,0 +1,70 @@
|
|||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//Outputs the natively demangled Swift symbol found at the current address in expanded tree form.
|
||||
//Mostly useful for debugging.
|
||||
//@category Demangler
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.util.demangler.DemangledObject;
|
||||
import ghidra.app.util.demangler.swift.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftNativeDemangler.SwiftNativeDemangledOutput;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
||||
public class SwiftDemanglerScript extends GhidraScript {
|
||||
|
||||
@Override
|
||||
protected void run() throws Exception {
|
||||
SwiftDemangler demangler = new SwiftDemangler();
|
||||
SwiftDemanglerOptions options = new SwiftDemanglerOptions();
|
||||
if (!demangler.canDemangle(currentProgram)) {
|
||||
println("Not a Swift program");
|
||||
return;
|
||||
}
|
||||
println("-------------------------------------------------");
|
||||
|
||||
String mangled = null;
|
||||
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||
for (Symbol symbol : symbolTable.getSymbols(currentAddress)) {
|
||||
if (demangler.isSwiftMangledSymbol(symbol.getName())) {
|
||||
mangled = symbol.getName();
|
||||
break;
|
||||
}
|
||||
for (LabelHistory history : symbolTable.getLabelHistory(currentAddress)) {
|
||||
if (demangler.isSwiftMangledSymbol(history.getLabelString())) {
|
||||
mangled = history.getLabelString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mangled == null) {
|
||||
println("No mangled Swift symbols found at " + currentAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
SwiftNativeDemangler nativeDemangler = new SwiftNativeDemangler(options.getSwiftDir());
|
||||
SwiftNativeDemangledOutput demangledOutput = nativeDemangler.demangle(mangled);
|
||||
println(demangledOutput.toString());
|
||||
|
||||
DemangledObject demangledObject = demangler.demangle(mangled);
|
||||
if (demangledObject != null) {
|
||||
println(demangledObject.getClass().getSimpleName() + " " + mangled + " --> " +
|
||||
demangledObject);
|
||||
}
|
||||
else {
|
||||
println("Failed to demangle: " + mangled);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/* ###
|
||||
* 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.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.framework.options.OptionType;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* An analyzer to demangle Swift mangled symbols
|
||||
*/
|
||||
public class SwiftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
|
||||
private static final String NAME = "Demangler Swift";
|
||||
private static final String DESCRIPTION =
|
||||
"Demangles Swift symbols and applies appropriate datatype and calling conventions where possible. Requires Swift to be installed.";
|
||||
private static final String OPTION_NAME_SWIFT_DIR = "Swift binary directory";
|
||||
private static final String OPTION_DESCRIPTION_SWIFT_DIR =
|
||||
"Path to the Swift installation binary directory, if not on PATH";
|
||||
|
||||
private static final String OPTION_NAME_INCOMPLETE_PREFIX =
|
||||
"Use incomplete demangle label prefix (%s)"
|
||||
.formatted(SwiftDemanglerOptions.INCOMPLETE_PREFIX);
|
||||
private static final String OPTION_DESCRIPTION_INCOMPLETE_PREFIX =
|
||||
"Prefix incomplete demangled labels with '%s'"
|
||||
.formatted(SwiftDemanglerOptions.INCOMPLETE_PREFIX);
|
||||
private static final String OPTION_NAME_UNSUPPORTED_PREFIX =
|
||||
"Use unsupported demangle label prefix (%s)"
|
||||
.formatted(SwiftDemanglerOptions.UNSUPPORTED_PREFIX);
|
||||
private static final String OPTION_DESCRIPTION_UNSUPPORTED_PREFIX =
|
||||
"Prefix unsupported demangled labels with '%s'"
|
||||
.formatted(SwiftDemanglerOptions.UNSUPPORTED_PREFIX);
|
||||
|
||||
private File swiftDir;
|
||||
private boolean useIncompletePrefix = true;
|
||||
private boolean useUnsupportedPrefix = true;
|
||||
private SwiftDemangler demangler = new SwiftDemangler();
|
||||
|
||||
/**
|
||||
* Creates a new {@link SwiftDemanglerAnalyzer}
|
||||
*/
|
||||
public SwiftDemanglerAnalyzer() {
|
||||
super(NAME, DESCRIPTION);
|
||||
setDefaultEnablement(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAnalyze(Program program) {
|
||||
return demangler.canDemangle(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DemangledObject doDemangle(String mangled, DemanglerOptions options, MessageLog log)
|
||||
throws DemangledException {
|
||||
return demangler.demangle(mangled, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analysisEnded(Program program) {
|
||||
demangler.clearCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOptions(Options options, Program program) {
|
||||
HelpLocation help = new HelpLocation("AutoAnalysisPlugin", "Demangler_Analyzer");
|
||||
options.registerOption(OPTION_NAME_SWIFT_DIR, OptionType.FILE_TYPE, swiftDir, help,
|
||||
OPTION_DESCRIPTION_SWIFT_DIR);
|
||||
options.registerOption(OPTION_NAME_INCOMPLETE_PREFIX, OptionType.BOOLEAN_TYPE,
|
||||
useIncompletePrefix, help, OPTION_DESCRIPTION_INCOMPLETE_PREFIX);
|
||||
options.registerOption(OPTION_NAME_UNSUPPORTED_PREFIX, OptionType.BOOLEAN_TYPE,
|
||||
useUnsupportedPrefix, help, OPTION_DESCRIPTION_UNSUPPORTED_PREFIX);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean validateOptions(DemanglerOptions options, MessageLog log) {
|
||||
if (options instanceof SwiftDemanglerOptions swiftDemanglerOptions) {
|
||||
try {
|
||||
new SwiftNativeDemangler(swiftDemanglerOptions.getSwiftDir());
|
||||
return true;
|
||||
}
|
||||
catch (IOException e) {
|
||||
log.appendMsg(e.getMessage());
|
||||
log.appendMsg("You must have Swift installed to demangle Swift symbols.\n" +
|
||||
"See the \"Demangler Swift\" analyzer options to configure.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void optionsChanged(Options options, Program program) {
|
||||
swiftDir = options.getFile(OPTION_NAME_SWIFT_DIR, swiftDir);
|
||||
useIncompletePrefix =
|
||||
options.getBoolean(OPTION_NAME_INCOMPLETE_PREFIX, useIncompletePrefix);
|
||||
useUnsupportedPrefix =
|
||||
options.getBoolean(OPTION_NAME_UNSUPPORTED_PREFIX, useUnsupportedPrefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DemanglerOptions getOptions() {
|
||||
SwiftDemanglerOptions swiftDemanglerOptions = new SwiftDemanglerOptions();
|
||||
swiftDemanglerOptions.setSwiftDir(swiftDir);
|
||||
swiftDemanglerOptions.setIncompletePrefix(useIncompletePrefix);
|
||||
swiftDemanglerOptions.setUnsupportedPrefix(useUnsupportedPrefix);
|
||||
return swiftDemanglerOptions;
|
||||
}
|
||||
}
|
|
@ -13,28 +13,22 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.bin.format.swift;
|
||||
package ghidra.app.util.demangler.swift;
|
||||
|
||||
import ghidra.app.util.bin.StructConverter;
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftNode;
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* Kinds of Swift demangling {@link SwiftNode}s
|
||||
*
|
||||
* @return The name of the {@link SwiftStructure}
|
||||
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/Demangling/DemangleNodes.def">DemangleNodes.def</a>
|
||||
*/
|
||||
public String getStructureName();
|
||||
public enum SwiftDemangledBuiltinType {
|
||||
//@formatter:off
|
||||
|
||||
/**
|
||||
* Gets a short description of the {@link SwiftStructure}
|
||||
*
|
||||
* @return A short description of the {@link SwiftStructure}
|
||||
*/
|
||||
public String getDescription();
|
||||
Int1,
|
||||
Word,
|
||||
RawPointer,
|
||||
Unsupported
|
||||
|
||||
//@formatter:on
|
||||
}
|
|
@ -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.demangler.swift;
|
||||
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftNode;
|
||||
|
||||
/**
|
||||
* Kinds of Swift demangling {@link SwiftNode}s
|
||||
*
|
||||
* @see <a href="https://github.com/apple/swift/blob/main/include/swift/Demangling/DemangleNodes.def">DemangleNodes.def</a>
|
||||
*/
|
||||
public enum SwiftDemangledNodeKind {
|
||||
//@formatter:off
|
||||
|
||||
Allocator,
|
||||
AnonymousDescriptor,
|
||||
ArgumentTuple,
|
||||
BoundGenericStructure,
|
||||
BuiltinTypeName,
|
||||
Class,
|
||||
Constructor,
|
||||
Deallocator,
|
||||
DefaultArgumentInitializer,
|
||||
DependentGenericParamType,
|
||||
DependentGenericType,
|
||||
Destructor,
|
||||
DispatchThunk,
|
||||
Enum,
|
||||
Extension,
|
||||
FirstElementMarker,
|
||||
Function,
|
||||
FunctionType,
|
||||
GenericSpecialization,
|
||||
Getter,
|
||||
Global,
|
||||
GlobalVariableOnceDeclList,
|
||||
GlobalVariableOnceFunction,
|
||||
Identifier,
|
||||
InfixOperator,
|
||||
Initializer,
|
||||
InOut,
|
||||
LabelList,
|
||||
LazyProtocolWitnessTableAccessor,
|
||||
LocalDeclName,
|
||||
MergedFunction,
|
||||
ModifyAccessor,
|
||||
Module,
|
||||
ModuleDescriptor,
|
||||
NominalTypeDescriptor,
|
||||
Number,
|
||||
ObjCAttribute,
|
||||
OutlinedConsume,
|
||||
OutlinedCopy,
|
||||
Owned,
|
||||
PrivateDeclName,
|
||||
Protocol,
|
||||
ProtocolConformance,
|
||||
ProtocolConformanceDescriptor,
|
||||
ProtocolDescriptor,
|
||||
ProtocolWitness,
|
||||
ReflectionMetadataBuiltinDescriptor,
|
||||
ReflectionMetadataFieldDescriptor,
|
||||
ReturnType,
|
||||
Setter,
|
||||
Static,
|
||||
Structure,
|
||||
Subscript,
|
||||
Suffix,
|
||||
Tuple,
|
||||
TupleElement,
|
||||
TupleElementName,
|
||||
Type,
|
||||
TypeAlias,
|
||||
TypeList,
|
||||
TypeMetadataAccessFunction,
|
||||
UnsafeMutableAddressor,
|
||||
Unsupported,
|
||||
Variable;
|
||||
|
||||
//@formatter:on
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/* ###
|
||||
* 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.demangler.swift;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import ghidra.app.util.demangler.swift.SwiftNativeDemangler.SwiftNativeDemangledOutput;
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftNode;
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftNode.NodeProperties;
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftUnsupportedNode;
|
||||
|
||||
/**
|
||||
* A Swift demangled symbol, structured as a tree of {@link SwiftNode nodes}
|
||||
* <p>
|
||||
* For example, the <code>Swift.print</code> function's mangled form is
|
||||
* <code>_$ss5print_9separator10terminatoryypd_S2StF</code>, and its demangled tree is:
|
||||
* <pre>
|
||||
* kind=Global
|
||||
* kind=Function
|
||||
* kind=Module, text="Swift"
|
||||
* kind=Identifier, text="print"
|
||||
* kind=LabelList
|
||||
* kind=FirstElementMarker
|
||||
* kind=Identifier, text="separator"
|
||||
* kind=Identifier, text="terminator"
|
||||
* kind=Type
|
||||
* kind=FunctionType
|
||||
* kind=ArgumentTuple
|
||||
* kind=Type
|
||||
* kind=Tuple
|
||||
* kind=TupleElement
|
||||
* kind=VariadicMarker
|
||||
* kind=Type
|
||||
* kind=ProtocolList
|
||||
* kind=TypeList
|
||||
* kind=TupleElement
|
||||
* kind=Type
|
||||
* kind=Structure
|
||||
* kind=Module, text="Swift"
|
||||
* kind=Identifier, text="String"
|
||||
* kind=TupleElement
|
||||
* kind=Type
|
||||
* kind=Structure
|
||||
* kind=Module, text="Swift"
|
||||
* kind=Identifier, text="String"
|
||||
* kind=ReturnType
|
||||
* kind=Type
|
||||
* kind=Tuple
|
||||
* </pre>
|
||||
*/
|
||||
public class SwiftDemangledTree {
|
||||
|
||||
private static final Pattern KIND_PATTERN = Pattern.compile("kind=([^,]+)");
|
||||
private static final Pattern TEXT_PATTERN = Pattern.compile("text=\"(.+)\"");
|
||||
private static final Pattern INDEX_PATTERN = Pattern.compile("index=(.+)");
|
||||
|
||||
private SwiftNode root;
|
||||
private String demangledString;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SwiftDemangledTree}
|
||||
*
|
||||
* @param nativeDemangler The Swift native demangler
|
||||
* @param mangled The mangled string
|
||||
* @throws IOException If there was an IO-related error
|
||||
*/
|
||||
public SwiftDemangledTree(SwiftNativeDemangler nativeDemangler, String mangled)
|
||||
throws IOException {
|
||||
SwiftNativeDemangledOutput demangledOutput = nativeDemangler.demangle(mangled);
|
||||
demangledString = demangledOutput.demangled();
|
||||
Stack<SwiftNode> stack = new Stack<>();
|
||||
for (String line : demangledOutput.tree()) {
|
||||
int depth = depth(line);
|
||||
String kind = match(line, KIND_PATTERN);
|
||||
String text = match(line, TEXT_PATTERN);
|
||||
String index = match(line, INDEX_PATTERN);
|
||||
SwiftNode node;
|
||||
try {
|
||||
NodeProperties properties = new NodeProperties(SwiftDemangledNodeKind.valueOf(kind),
|
||||
text, index, depth, mangled, demangledString);
|
||||
node = SwiftNode.get(properties);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
NodeProperties properties = new NodeProperties(SwiftDemangledNodeKind.Unsupported,
|
||||
text, index, depth, mangled, demangledString);
|
||||
node = new SwiftUnsupportedNode(kind, properties);
|
||||
}
|
||||
if (node.getDepth() == 0) {
|
||||
root = node;
|
||||
}
|
||||
else {
|
||||
if (node.getDepth() <= stack.peek().getDepth()) {
|
||||
while (stack.peek().getDepth() > node.getDepth() - 1) {
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
node.setParent(stack.peek());
|
||||
stack.peek().getChildren().add(node);
|
||||
}
|
||||
stack.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the root {@link SwiftNode} of the tree
|
||||
*
|
||||
* @return The root {@link SwiftNode} of the tree. Could be null if demangling finished
|
||||
* gracefully but did not return a result.
|
||||
*/
|
||||
public SwiftNode getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the demangled string
|
||||
*
|
||||
* @return The demangled string. Could be null if demangling finished gracefully
|
||||
* but did not return a result.
|
||||
*/
|
||||
public String getDemangledString() {
|
||||
return demangledString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return SwiftNode.toString(root, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tree-depth of this {@link SwiftNode}
|
||||
*
|
||||
* @param line A line of output from <code>swift demangle --tree-only</code>
|
||||
* @return The tree-depth of this {@link SwiftNode}
|
||||
*/
|
||||
private int depth(String line) {
|
||||
int i = 0;
|
||||
while (i < line.length() && line.charAt(i) == ' ') {
|
||||
i++;
|
||||
}
|
||||
return i / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a matched pattern on the given line
|
||||
*
|
||||
* @param line The line to match against
|
||||
* @param pattern The {@link Pattern} to match
|
||||
* @return The matched string, or null if there was no match
|
||||
*/
|
||||
private String match(String line, Pattern pattern) {
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
return matcher.find() ? matcher.group(1) : null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
/* ###
|
||||
* 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.demangler.swift;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftDataTypeUtils;
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftNode;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A demangler for mangled Swift symbols
|
||||
*/
|
||||
public class SwiftDemangler implements Demangler {
|
||||
|
||||
private Program program;
|
||||
private SwiftTypeMetadata typeMetadata;
|
||||
private SwiftNativeDemangler nativeDemangler;
|
||||
private SwiftDemanglerOptions options;
|
||||
private Map<String, SwiftNode> cache;
|
||||
private DemangledException initException;
|
||||
|
||||
@Override
|
||||
public boolean canDemangle(Program p) {
|
||||
this.program = p;
|
||||
return SwiftUtils.isSwift(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemanglerOptions createDefaultOptions() {
|
||||
return new SwiftDemanglerOptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemangledObject demangle(String mangled, boolean demangleOnlyKnownPatterns)
|
||||
throws DemangledException {
|
||||
return demangle(mangled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes class variables
|
||||
*
|
||||
* @param opt The options
|
||||
* @throws DemangledException If there was an issue with initialization
|
||||
*/
|
||||
private void init(DemanglerOptions opt) throws DemangledException {
|
||||
if (initException != null) {
|
||||
throw initException;
|
||||
}
|
||||
|
||||
if (program != null && typeMetadata == null) {
|
||||
try {
|
||||
program.setPreferredRootNamespaceCategoryPath(
|
||||
SwiftDataTypeUtils.SWIFT_CATEGORY.getPath());
|
||||
typeMetadata = new SwiftTypeMetadata(program, TaskMonitor.DUMMY, new MessageLog());
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
return;
|
||||
}
|
||||
catch (IOException e) {
|
||||
initException = new DemangledException(e);
|
||||
throw initException;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt != null) {
|
||||
options = getSwiftDemanglerOptions(opt);
|
||||
}
|
||||
|
||||
if (nativeDemangler == null) {
|
||||
try {
|
||||
nativeDemangler = new SwiftNativeDemangler(options.getSwiftDir());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new DemangledException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (cache == null) {
|
||||
cache = new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Demangles the given mangled string
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The demangled string produced by the native Swift demangler
|
||||
* @param meta The {@link SwiftTypeMetadata}, or null if unavailable
|
||||
* @return The {@link Demangled} object, or null if the mangled string is not a supported Swift
|
||||
* symbol
|
||||
* @throws DemangledException if a problem occurred
|
||||
*/
|
||||
public Demangled demangle(String mangled, String originalDemangled, SwiftTypeMetadata meta)
|
||||
throws DemangledException {
|
||||
if (!isSwiftMangledSymbol(mangled)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
SwiftNode root;
|
||||
if (cache.containsKey(mangled)) {
|
||||
root = cache.get(mangled);
|
||||
}
|
||||
else {
|
||||
SwiftDemangledTree tree = new SwiftDemangledTree(nativeDemangler, mangled);
|
||||
root = tree.getRoot();
|
||||
}
|
||||
cache.put(mangled, root);
|
||||
if (root == null) {
|
||||
return null;
|
||||
}
|
||||
Demangled demangled = root.demangle(this, meta);
|
||||
if (root.walkAndTest(node -> node.childWasSkipped())) {
|
||||
demangled.setName(options.getIncompletePrefix() + demangled.getName());
|
||||
}
|
||||
return demangled;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new DemangledException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemangledObject demangle(String mangled, DemanglerOptions opt)
|
||||
throws DemangledException {
|
||||
|
||||
init(opt);
|
||||
|
||||
Demangled demangled = demangle(mangled, null, typeMetadata);
|
||||
if (demangled instanceof DemangledFunction func) {
|
||||
return func;
|
||||
}
|
||||
else if (demangled instanceof DemangledLabel label) {
|
||||
return label;
|
||||
}
|
||||
else if (demangled instanceof DemangledUnknown unknown) {
|
||||
return new DemangledLabel(mangled, unknown.getOriginalDemangled(),
|
||||
options.getUnsupportedPrefix() + unknown.getOriginalDemangled());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache
|
||||
*/
|
||||
public void clearCache() {
|
||||
if (cache != null) {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether the given symbol name is a mangled Swift symbol
|
||||
*
|
||||
* @param symbolName The symbol name to check
|
||||
* @return True if the given symbol name is a mangled Swift symbol; otherwise, false
|
||||
*/
|
||||
public boolean isSwiftMangledSymbol(String symbolName) {
|
||||
List<String> prefixes = List.of("$S", "$s", "_$S", "_$s", "_T");
|
||||
return prefixes.stream().anyMatch(prefix -> symbolName.startsWith(prefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link SwiftDemanglerOptions} from the given {@link DemanglerOptions}
|
||||
*
|
||||
* @param opt The options
|
||||
* @return The @link SwiftDemanglerOptions}
|
||||
* @throws DemangledException If the given options are not {@link SwiftDemanglerOptions}
|
||||
*/
|
||||
public SwiftDemanglerOptions getSwiftDemanglerOptions(DemanglerOptions opt)
|
||||
throws DemangledException {
|
||||
if (!(opt instanceof SwiftDemanglerOptions)) {
|
||||
opt = createDefaultOptions();
|
||||
}
|
||||
return (SwiftDemanglerOptions) opt;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.demangler.swift;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import ghidra.app.util.demangler.DemanglerOptions;
|
||||
|
||||
/**
|
||||
* Swift demangler options
|
||||
*/
|
||||
public class SwiftDemanglerOptions extends DemanglerOptions {
|
||||
|
||||
public static final String INCOMPLETE_PREFIX = "$";
|
||||
public static final String UNSUPPORTED_PREFIX = "$$";
|
||||
|
||||
private File swiftDir;
|
||||
private boolean useIncompletePrefix;
|
||||
private boolean useUnsupportedPrefix;
|
||||
|
||||
/**
|
||||
* Gets the Swift directory
|
||||
* <p>
|
||||
* If the Swift directory is on the PATH environment variable, this may return null
|
||||
*
|
||||
* @return The Swift directory
|
||||
*/
|
||||
public File getSwiftDir() {
|
||||
return swiftDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Swift directory
|
||||
* <p>
|
||||
* If the Swift directory is on the PATH environment variable, it is fine to set this to
|
||||
* null
|
||||
*
|
||||
* @param swiftDir The Swift directory
|
||||
*/
|
||||
public void setSwiftDir(File swiftDir) {
|
||||
this.swiftDir = swiftDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the "incomplete prefix" character to use in label names}
|
||||
*/
|
||||
public String getIncompletePrefix() {
|
||||
return useIncompletePrefix ? INCOMPLETE_PREFIX : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not to use an "incomplete prefix" character in label names
|
||||
*
|
||||
* @param incompletePrefix True if labels should include an "incomplete prefix" character
|
||||
* in their name; otherwise, false
|
||||
*/
|
||||
public void setIncompletePrefix(boolean incompletePrefix) {
|
||||
this.useIncompletePrefix = incompletePrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the "unsupported prefix" character to use in label names}
|
||||
*/
|
||||
public String getUnsupportedPrefix() {
|
||||
return useUnsupportedPrefix ? UNSUPPORTED_PREFIX : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not to use an "unsupported prefix" character in label names
|
||||
*
|
||||
* @param unsupportedPrefix True if labels should include an "unsupported prefix" character
|
||||
* in their name; otherwise, false
|
||||
*/
|
||||
public void setUnsupportedPrefix(boolean unsupportedPrefix) {
|
||||
this.useUnsupportedPrefix = unsupportedPrefix;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/* ###
|
||||
* 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.demangler.swift;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A class used to launch the Swift native demangler.
|
||||
* <p>
|
||||
* The Swift native demangler binary comes in 2 forms, and can thus be invoked in 2 ways:
|
||||
* <ul>
|
||||
* <li>{@code ./swift demangle args}</li>
|
||||
* <li>{@code ./swift-demangle args}</li>
|
||||
* </ul>
|
||||
*
|
||||
* The latter is how it is done in the Windows version of Swift. We will refer to this version
|
||||
* as the "standalone demangler binary".
|
||||
*/
|
||||
public class SwiftNativeDemangler {
|
||||
|
||||
private String nativeDemanglerPath;
|
||||
private boolean standaloneDemanglerBinary;
|
||||
|
||||
/**
|
||||
* The output of the native Swift demangler
|
||||
*
|
||||
* @param demangled The demangled string
|
||||
* @param tree The lines of the demangled expanded tree
|
||||
*/
|
||||
public record SwiftNativeDemangledOutput(String demangled, List<String> tree) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "%s\n%s".formatted(demangled != null ? demangled : "<NULL>",
|
||||
tree.stream().collect(Collectors.joining("\n")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SwiftNativeDemangler}
|
||||
*
|
||||
* @param swiftDir The Swift directory
|
||||
* @throws IOException if there was a problem finding or running the Swift native demangler
|
||||
*/
|
||||
public SwiftNativeDemangler(File swiftDir) throws IOException {
|
||||
List<String> demanglerNames = List.of("swift-demangle", "swift");
|
||||
IOException ioe = null;
|
||||
for (String demanglerName : demanglerNames) {
|
||||
nativeDemanglerPath = demanglerName;
|
||||
if (swiftDir != null) {
|
||||
nativeDemanglerPath = swiftDir + File.separator + nativeDemanglerPath;
|
||||
}
|
||||
try {
|
||||
int exitCode =
|
||||
new ProcessBuilder(List.of(nativeDemanglerPath, "--version")).start()
|
||||
.waitFor();
|
||||
if (exitCode == 0) {
|
||||
ioe = null;
|
||||
standaloneDemanglerBinary =
|
||||
new File(nativeDemanglerPath).getName().contains("-demangle");
|
||||
break;
|
||||
}
|
||||
ioe = new IOException("Native Swift demangler exited with code: " + exitCode);
|
||||
}
|
||||
catch (IOException e) {
|
||||
ioe = e;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
ioe = new IOException(e);
|
||||
}
|
||||
}
|
||||
if (ioe != null) {
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the Swift executable to demangle the given mangled string
|
||||
*
|
||||
* @param mangled The mangled string to demangle
|
||||
* @return The {@link SwiftNativeDemangledOutput}
|
||||
* @throws IOException If there was an IO-related issue
|
||||
* @see SwiftDemangledTree
|
||||
*/
|
||||
public SwiftNativeDemangledOutput demangle(String mangled) throws IOException {
|
||||
List<String> demanglerArgs = new ArrayList<>();
|
||||
demanglerArgs.add("--compact"); // Compact mode (only emit the demangled names)
|
||||
demanglerArgs.add("--expand"); // Expand mode (show node structure of the demangling)
|
||||
try (BufferedReader reader = demangle(mangled, demanglerArgs)) {
|
||||
String demangled = null;
|
||||
List<String> treeLines = new ArrayList<>();
|
||||
String line = reader.readLine().trim();
|
||||
if (!line.startsWith("Demangling for")) {
|
||||
throw new IOException("Unexpected output: " + line);
|
||||
}
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.startsWith("<<NULL>>")) { // Not a demangleable string
|
||||
break;
|
||||
}
|
||||
if (line.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
if (treeLines.isEmpty() && !line.trim().startsWith("kind")) {
|
||||
// This case is mainly for when the mangled string has newline characters in it,
|
||||
// which are printed in the first "Demangling for..." line. We want to skip
|
||||
// those and get to the tree.
|
||||
continue;
|
||||
}
|
||||
if (!treeLines.isEmpty() && !line.startsWith(" ")) {
|
||||
// This case should grab the last line after the tree, which is the full
|
||||
// demangled string
|
||||
demangled = line;
|
||||
break;
|
||||
}
|
||||
treeLines.add(line);
|
||||
}
|
||||
return new SwiftNativeDemangledOutput(demangled, treeLines);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the Swift demangler to demangled the given mangled string with the given demangle
|
||||
* options
|
||||
*
|
||||
* @param mangled The mangled string to demangle
|
||||
* @param options Additional demangle options
|
||||
* @return A {@link BufferedReader} used to read the output of the executed command
|
||||
* @throws IOException If there was an IO-related issue
|
||||
*/
|
||||
private BufferedReader demangle(String mangled, List<String> options) throws IOException {
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add(nativeDemanglerPath);
|
||||
if (!standaloneDemanglerBinary) {
|
||||
command.add("demangle");
|
||||
}
|
||||
command.addAll(options);
|
||||
command.add(mangled);
|
||||
Process p = new ProcessBuilder(command).redirectErrorStream(true).start();
|
||||
return new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
}
|
||||
}
|
|
@ -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.util.demangler.swift.datatypes;
|
||||
|
||||
import ghidra.app.util.demangler.DemangledDataType;
|
||||
|
||||
/**
|
||||
* A Swift array
|
||||
*/
|
||||
public class SwiftArray extends DemangledDataType {
|
||||
|
||||
private DemangledDataType boundType;
|
||||
|
||||
/**
|
||||
* Creates a new Swift array bound to the "undefined" type
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
*/
|
||||
public SwiftArray(String mangled, String originalDemangled) {
|
||||
super(mangled, originalDemangled, "Array");
|
||||
setNamespace(SwiftDataTypeUtils.SWIFT_NAMESPACE);
|
||||
setBoundType(
|
||||
new DemangledDataType(mangled, originalDemangled, DemangledDataType.UNDEFINED));
|
||||
setArray(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the bound type}
|
||||
*/
|
||||
public DemangledDataType getBoundType() {
|
||||
return boundType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bound type
|
||||
*
|
||||
* @param type The bound type
|
||||
*/
|
||||
public void setBoundType(DemangledDataType type) {
|
||||
boundType = type;
|
||||
setName("Array<%s>".formatted(type.getName()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.datatypes;
|
||||
|
||||
import ghidra.app.util.demangler.DemangledDataType;
|
||||
import ghidra.app.util.demangler.DemangledStructure;
|
||||
|
||||
/**
|
||||
* A Swift character
|
||||
*/
|
||||
public class SwiftCharacter extends DemangledStructure {
|
||||
|
||||
/**
|
||||
* Creates a new Swift character
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
*/
|
||||
public SwiftCharacter(String mangled, String originalDemangled) {
|
||||
super(mangled, originalDemangled, "Character",
|
||||
SwiftDataTypeUtils.getCategoryPath(SwiftDataTypeUtils.SWIFT_NAMESPACE).getPath(), true);
|
||||
setNamespace(SwiftDataTypeUtils.SWIFT_NAMESPACE);
|
||||
|
||||
DemangledDataType stringDt = new DemangledDataType(mangled, null, DemangledDataType.CHAR);
|
||||
stringDt.incrementPointerLevels();
|
||||
|
||||
DemangledDataType voidDt = new DemangledDataType(mangled, null, DemangledDataType.VOID);
|
||||
voidDt.incrementPointerLevels();
|
||||
|
||||
addField("str", stringDt);
|
||||
addField("bridgeObject", voidDt);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.datatypes;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.program.model.data.CategoryPath;
|
||||
|
||||
/**
|
||||
* Swift data type utilities
|
||||
*/
|
||||
public class SwiftDataTypeUtils {
|
||||
|
||||
/**
|
||||
* Default path to store Swift data structures in the data type manager
|
||||
*/
|
||||
public static final CategoryPath SWIFT_CATEGORY = new CategoryPath("/Demangler");
|
||||
|
||||
/**
|
||||
* A {@link Demangled} to represent the standard Swift namespace
|
||||
*/
|
||||
public static final Demangled SWIFT_NAMESPACE = new DemangledUnknown("", null, "Swift");
|
||||
|
||||
/**
|
||||
* Checks to see if the given namespace is the standard Swift namespace
|
||||
*
|
||||
* @param namespace The namespace to check
|
||||
* @return True if the given namespace is the standard Swift namespace; otherwise, false
|
||||
*/
|
||||
public static boolean isSwiftNamespace(Demangled namespace) {
|
||||
return namespace != null && namespace.getName().equals(SWIFT_NAMESPACE.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link CategoryPath} based on the given namespace
|
||||
*
|
||||
* @param namespace The namespace
|
||||
* @return A {@link CategoryPath} based on the given namespace
|
||||
*/
|
||||
public static CategoryPath getCategoryPath(Demangled namespace) {
|
||||
if (namespace == null) {
|
||||
return SWIFT_CATEGORY;
|
||||
}
|
||||
LinkedList<String> path = new LinkedList<>();
|
||||
while (namespace != null) {
|
||||
path.addFirst(namespace.getNamespaceName());
|
||||
namespace = namespace.getNamespace();
|
||||
}
|
||||
return new CategoryPath(SWIFT_CATEGORY, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link List} of {@link DemangledParameter parameters} found within the given
|
||||
* {@link Demangled} object
|
||||
*
|
||||
* @param demangled A {@link Demangled} object
|
||||
* @return A {@link List} of {@link DemangledParameter parameters} found within the given
|
||||
* {@link Demangled} object
|
||||
*/
|
||||
public static List<DemangledParameter> extractParameters(Demangled demangled) {
|
||||
List<DemangledParameter> params = new ArrayList<>();
|
||||
if (demangled instanceof DemangledVariable variable) {
|
||||
demangled = variable.getDataType();
|
||||
}
|
||||
if (demangled instanceof DemangledList list) {
|
||||
for (Demangled d : list) {
|
||||
if (d instanceof DemangledDataType type) {
|
||||
params.add(new DemangledParameter(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (demangled instanceof DemangledDataType type) {
|
||||
params.add(new DemangledParameter(type));
|
||||
}
|
||||
return params;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.datatypes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A Swift structure
|
||||
*/
|
||||
public class SwiftEnum extends DemangledStructure {
|
||||
|
||||
/**
|
||||
* Creates a new Swift enum
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
* @param name The enum name
|
||||
* @param namespace The enum namespace (could be null)
|
||||
* @param typeMetadata The {@link SwiftTypeMetadata}, or null if it is not known
|
||||
* @param demangler A {@link SwiftDemangler}
|
||||
* @throws DemangledException if a problem occurred
|
||||
*/
|
||||
public SwiftEnum(String mangled, String originalDemangled, String name,
|
||||
Demangled namespace, SwiftTypeMetadata typeMetadata, SwiftDemangler demangler)
|
||||
throws DemangledException {
|
||||
super(mangled, originalDemangled, name,
|
||||
SwiftDataTypeUtils.getCategoryPath(namespace).getPath(), true);
|
||||
setNamespace(namespace);
|
||||
|
||||
// The mangled output doesn't seem to indicate what field of the enum is being used, so
|
||||
// it's not currently clear how to query the type metadata for real type information.
|
||||
// Raw enums seem to just be bytes, so for now we'll just use a struct with 1 byte entry.
|
||||
DemangledDataType dt =
|
||||
new DemangledDataType(mangled, originalDemangled, DemangledDataType.INT8);
|
||||
addField("value", null, dt);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.datatypes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.demangler.*;
|
||||
|
||||
/**
|
||||
* A Swift function
|
||||
*/
|
||||
public class SwiftFunction extends DemangledFunction {
|
||||
|
||||
/**
|
||||
* Creates a new Swift function
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
* @param name The function name
|
||||
* @param namespace The function namespace (could be null)
|
||||
* @param callingConvention The function calling convention (could be null)
|
||||
*/
|
||||
public SwiftFunction(String mangled, String originalDemangled, String name, Demangled namespace,
|
||||
String callingConvention) {
|
||||
super(mangled, originalDemangled, name);
|
||||
setNamespace(namespace);
|
||||
setCallingConvention(callingConvention);
|
||||
}
|
||||
|
||||
public void setType(DemangledFunction type, Demangled labelList) {
|
||||
setReturnType(type.getReturnType());
|
||||
List<DemangledParameter> params = type.getParameters();
|
||||
for (int i = 0; i < params.size(); i++) {
|
||||
DemangledParameter param = params.get(i);
|
||||
if (labelList instanceof DemangledList list && i < list.size() &&
|
||||
list.get(i) instanceof DemangledLabel label) {
|
||||
param.setLabel(label.getName());
|
||||
}
|
||||
addParameter(param);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.datatypes;
|
||||
|
||||
import ghidra.app.util.demangler.DemangledDataType;
|
||||
|
||||
/**
|
||||
* A Swift primitive
|
||||
*/
|
||||
public class SwiftPrimitive extends DemangledDataType {
|
||||
|
||||
/**
|
||||
* Creates a new Swift primitive
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
* @param name The primitive name
|
||||
*/
|
||||
public SwiftPrimitive(String mangled, String originalDemangled, String name) {
|
||||
super(mangled, originalDemangled, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Swift primitive
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
* @param name The primitive name
|
||||
* @param unsigned True if the primitive should be unsigned; otherwise, false
|
||||
*/
|
||||
public SwiftPrimitive(String mangled, String originalDemangled, String name, boolean unsigned) {
|
||||
this(mangled, originalDemangled, name);
|
||||
setUnsigned();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.datatypes;
|
||||
|
||||
import ghidra.app.util.demangler.DemangledDataType;
|
||||
import ghidra.app.util.demangler.DemangledStructure;
|
||||
|
||||
/**
|
||||
* A Swift string
|
||||
*/
|
||||
public class SwiftString extends DemangledStructure {
|
||||
|
||||
/**
|
||||
* Creates a new Swift string
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
*/
|
||||
public SwiftString(String mangled, String originalDemangled) {
|
||||
super(mangled, originalDemangled, "String",
|
||||
SwiftDataTypeUtils.getCategoryPath(SwiftDataTypeUtils.SWIFT_NAMESPACE).getPath(), true);
|
||||
setNamespace(SwiftDataTypeUtils.SWIFT_NAMESPACE);
|
||||
|
||||
DemangledDataType stringDt = new DemangledDataType(mangled, null, DemangledDataType.CHAR);
|
||||
stringDt.incrementPointerLevels();
|
||||
|
||||
DemangledDataType voidDt = new DemangledDataType(mangled, null, DemangledDataType.VOID);
|
||||
voidDt.incrementPointerLevels();
|
||||
|
||||
addField("str", stringDt);
|
||||
addField("bridgeObject", voidDt);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.datatypes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.bin.format.swift.types.*;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A Swift structure
|
||||
*/
|
||||
public class SwiftStructure extends DemangledStructure {
|
||||
|
||||
/**
|
||||
* Creates a new Swift structure
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
* @param name The structure name
|
||||
* @param namespace The structure namespace (could be null)
|
||||
* @param typeMetadata The {@link SwiftTypeMetadata}, or null if it is not known
|
||||
* @param demangler A {@link SwiftDemangler}
|
||||
* @throws DemangledException if a problem occurred
|
||||
*/
|
||||
public SwiftStructure(String mangled, String originalDemangled, String name,
|
||||
Demangled namespace, SwiftTypeMetadata typeMetadata, SwiftDemangler demangler)
|
||||
throws DemangledException {
|
||||
super(mangled, originalDemangled, name,
|
||||
SwiftDataTypeUtils.getCategoryPath(namespace).getPath(), true);
|
||||
setNamespace(namespace);
|
||||
|
||||
// Try to add structure fields from the type metadata
|
||||
if (typeMetadata != null) {
|
||||
TargetTypeContextDescriptor typeDescriptor =
|
||||
typeMetadata.getTargetTypeContextDescriptors().get(name);
|
||||
if (typeDescriptor != null) {
|
||||
FieldDescriptor fieldDescriptor =
|
||||
typeDescriptor.getFieldDescriptor(typeMetadata.getFieldDescriptors());
|
||||
if (fieldDescriptor != null) {
|
||||
for (FieldRecord fieldRecord : fieldDescriptor.getFieldRecords()) {
|
||||
String mangledType = "_T" + fieldRecord.getMangledTypeName();
|
||||
Demangled demangled =
|
||||
demangler.demangle(mangledType, originalDemangled, typeMetadata);
|
||||
if (demangled instanceof DemangledDataType ddt) {
|
||||
addField(fieldRecord.getFieldName(), fieldRecord.getDescription(), ddt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.datatypes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A Swift tuple
|
||||
*/
|
||||
public class SwiftTuple extends SwiftStructure {
|
||||
|
||||
/**
|
||||
* Creates a new Swift tuple
|
||||
*
|
||||
* @param mangled The mangled string
|
||||
* @param originalDemangled The natively demangled string
|
||||
* @param list The elements of the tuple
|
||||
* @param typeMetadata The {@link SwiftTypeMetadata}, or null if it is not known
|
||||
* @param demangler A {@link SwiftDemangler}
|
||||
* @throws DemangledException if a problem occurred
|
||||
*/
|
||||
public SwiftTuple(String mangled, String originalDemangled, DemangledList list,
|
||||
SwiftTypeMetadata typeMetadata, SwiftDemangler demangler) throws DemangledException {
|
||||
super(mangled, originalDemangled, "tuple%d".formatted(list.size()), null, typeMetadata,
|
||||
demangler);
|
||||
|
||||
int i = 0;
|
||||
for (Demangled element : list) {
|
||||
if (element instanceof DemangledDataType ddt) {
|
||||
addField(Integer.toString(i), ddt);
|
||||
}
|
||||
else if (element instanceof DemangledVariable variable) {
|
||||
addField(variable.getName(), variable.getDataType());
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Allocator} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftAllocatorNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
Demangled type = null;
|
||||
Demangled labelList = null;
|
||||
String callingConvention = CompilerSpec.CALLING_CONVENTION_default;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Class:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "__allocating_init";
|
||||
callingConvention = CompilerSpec.CALLING_CONVENTION_thiscall;
|
||||
break;
|
||||
case Extension:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
if (child.hasChild(SwiftDemangledNodeKind.Class)) {
|
||||
name = "__allocating_init";
|
||||
callingConvention = CompilerSpec.CALLING_CONVENTION_thiscall;
|
||||
}
|
||||
else if (child.hasChild(SwiftDemangledNodeKind.Protocol) ||
|
||||
child.hasChild(SwiftDemangledNodeKind.Structure)) {
|
||||
name = "init";
|
||||
}
|
||||
else {
|
||||
return getUnknown();
|
||||
}
|
||||
break;
|
||||
case Enum:
|
||||
case Protocol:
|
||||
case Structure:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "init";
|
||||
break;
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case LabelList:
|
||||
labelList = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
SwiftFunction function = new SwiftFunction(properties.mangled(),
|
||||
properties.originalDemangled(), name, namespace, callingConvention);
|
||||
if (type instanceof SwiftFunction functionType) {
|
||||
function.setType(functionType, labelList);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.demangler.swift.nodes;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftArray;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#BoundGenericStructure} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftBoundGenericStructureNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled type = null;
|
||||
Demangled typeList = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case TypeList:
|
||||
typeList = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type instanceof SwiftArray arr) {
|
||||
if (typeList instanceof DemangledList list && !list.isEmpty()) {
|
||||
Demangled first = list.get(0);
|
||||
if (first instanceof DemangledDataType ddt) {
|
||||
arr.setBoundType(ddt);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
if (typeList instanceof DemangledList list) {
|
||||
String typeNames = list
|
||||
.stream()
|
||||
.map(e -> e.getName())
|
||||
.collect(Collectors.joining(","));
|
||||
type.setName("%s<%s>".formatted(type.getName(), typeNames));
|
||||
return type;
|
||||
}
|
||||
|
||||
return getUnknown();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledDataType;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#BuiltinTypeName} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftBuiltinTypeNameNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata) {
|
||||
String orig = getText();
|
||||
String name = switch (orig) {
|
||||
case "Builtin.Int1":
|
||||
yield DemangledDataType.INT8;
|
||||
case "Builtin.Word":
|
||||
yield DemangledDataType.INT16;
|
||||
case "Builtin.RawPointer":
|
||||
yield DemangledDataType.VOID;
|
||||
default:
|
||||
yield orig;
|
||||
};
|
||||
DemangledDataType type =
|
||||
new DemangledDataType(properties.mangled(), properties.originalDemangled(), name);
|
||||
if (orig.equals("Builtin.RawPointer")) {
|
||||
type.incrementPointerLevels();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Class} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftClassNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
Demangled privateDeclNamespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
name = child.getText();
|
||||
break;
|
||||
case PrivateDeclName:
|
||||
Demangled temp = child.demangle(demangler, typeMetadata);
|
||||
name = temp.getName();
|
||||
privateDeclNamespace = temp.getNamespace();
|
||||
break;
|
||||
case Class:
|
||||
case Module:
|
||||
case Structure:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
DemangledDataType type =
|
||||
new DemangledDataType(properties.mangled(), properties.originalDemangled(), name);
|
||||
type.setNamespace(SwiftNode.join(namespace, privateDeclNamespace));
|
||||
type.setClass();
|
||||
type.incrementPointerLevels();
|
||||
return type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Constructor} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftConstructorNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
Demangled type = null;
|
||||
Demangled labelList = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Class:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "init";
|
||||
break;
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case LabelList:
|
||||
labelList = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
SwiftFunction function =
|
||||
new SwiftFunction(properties.mangled(), properties.originalDemangled(), name, namespace,
|
||||
CompilerSpec.CALLING_CONVENTION_thiscall);
|
||||
if (type instanceof DemangledFunction functionType) {
|
||||
function.setType(functionType, labelList);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Deallocator} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftDeallocatorNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Class:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "__deallocating_init";
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
return new SwiftFunction(properties.mangled(), properties.originalDemangled(), name,
|
||||
namespace, CompilerSpec.CALLING_CONVENTION_thiscall);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledDataType;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#DependentGenericParamType} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftDependentGenericParamTypeNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata) {
|
||||
// We don't really support this yet
|
||||
return new DemangledDataType(properties.mangled(), properties.originalDemangled(),
|
||||
DemangledDataType.UNDEFINED);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#DependentGenericType} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftDependentGenericTypeNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled type = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
|
@ -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.util.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Destructor} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftDestructorNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Class:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "deinit";
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
SwiftFunction function =
|
||||
new SwiftFunction(properties.mangled(), properties.originalDemangled(), name, namespace,
|
||||
CompilerSpec.CALLING_CONVENTION_thiscall);
|
||||
if (namespace instanceof DemangledDataType type) {
|
||||
function.setReturnType(type);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftEnum;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Enum} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftEnumNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
Demangled privateDeclNamespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
name = child.getText();
|
||||
break;
|
||||
case PrivateDeclName:
|
||||
Demangled temp = child.demangle(demangler, typeMetadata);
|
||||
name = temp.getName();
|
||||
privateDeclNamespace = temp.getNamespace();
|
||||
break;
|
||||
case Class:
|
||||
case Extension:
|
||||
case Module:
|
||||
case Structure:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
return new SwiftEnum(properties.mangled(), properties.originalDemangled(), name,
|
||||
SwiftNode.join(namespace, privateDeclNamespace), typeMetadata, demangler);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Extension} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftExtensionNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled namespace = null;
|
||||
Demangled type = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Module:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
namespace.setName("(extension_" + namespace.getName() + ")");
|
||||
break;
|
||||
case Class:
|
||||
case Enum:
|
||||
case Protocol:
|
||||
case Structure:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type == null || namespace == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
Demangled typeNamespace = type.getNamespace();
|
||||
if (typeNamespace != null) {
|
||||
typeNamespace.setNamespace(namespace);
|
||||
}
|
||||
else {
|
||||
type.setNamespace(namespace);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Function} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftFunctionNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
Demangled type = null;
|
||||
Demangled labelList = null;
|
||||
String callingConvention = CompilerSpec.CALLING_CONVENTION_default;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
name = child.getText();
|
||||
break;
|
||||
case InfixOperator:
|
||||
name = child.getText() + " infix";
|
||||
break;
|
||||
case LocalDeclName:
|
||||
name = child.demangle(demangler, typeMetadata).getName();
|
||||
break;
|
||||
case Class:
|
||||
callingConvention = CompilerSpec.CALLING_CONVENTION_thiscall;
|
||||
// Fall through
|
||||
case Enum:
|
||||
case Extension:
|
||||
case Function:
|
||||
case Module:
|
||||
case Protocol:
|
||||
case Structure:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case LabelList:
|
||||
labelList = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
SwiftFunction function = new SwiftFunction(properties.mangled(),
|
||||
properties.originalDemangled(), name, namespace, callingConvention);
|
||||
if (type instanceof DemangledFunction functionType) {
|
||||
function.setType(functionType, labelList);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.*;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#FunctionType} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftFunctionTypeNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled argumentTuple = null;
|
||||
Demangled returnType = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case ArgumentTuple:
|
||||
argumentTuple = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case ReturnType:
|
||||
returnType = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SwiftFunction function =
|
||||
new SwiftFunction(properties.mangled(), properties.originalDemangled(), "<unknown>",
|
||||
null, CompilerSpec.CALLING_CONVENTION_default);
|
||||
|
||||
// Parameters
|
||||
function.addParameters(SwiftDataTypeUtils.extractParameters(argumentTuple));
|
||||
|
||||
// Seems like when calling a struct (or enum) method, the "this" struct is passed after the
|
||||
// explicit parameters
|
||||
SwiftNode functionAncestor =
|
||||
getFirstAncestor(SwiftDemangledNodeKind.Function, SwiftDemangledNodeKind.Getter);
|
||||
if (functionAncestor != null) {
|
||||
if (functionAncestor.getKind().equals(SwiftDemangledNodeKind.Getter)) {
|
||||
functionAncestor = functionAncestor.getChildren().get(0);
|
||||
}
|
||||
SwiftNode struct = functionAncestor.getChild(SwiftDemangledNodeKind.Structure);
|
||||
SwiftNode enumm = functionAncestor.getChild(SwiftDemangledNodeKind.Enum);
|
||||
if (struct != null) {
|
||||
if (struct.demangle(demangler, typeMetadata) instanceof DemangledDataType type) {
|
||||
function.addParameter(new DemangledParameter(type));
|
||||
}
|
||||
}
|
||||
else if (enumm != null) {
|
||||
if (enumm.demangle(demangler, typeMetadata) instanceof DemangledDataType type) {
|
||||
function.addParameter(new DemangledParameter(type));
|
||||
// Enums are currently represented as single field structures, but in reality,
|
||||
// there could be more fields. Add a varargs parameter so these other fields
|
||||
// can show up in the decompiler.
|
||||
DemangledDataType varargs = new DemangledDataType(properties.mangled(),
|
||||
properties.originalDemangled(), DemangledDataType.UNDEFINED);
|
||||
varargs.setVarArgs();
|
||||
function.addParameter(new DemangledParameter(varargs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return type
|
||||
if (returnType instanceof DemangledDataType type) {
|
||||
function.setReturnType(type);
|
||||
}
|
||||
else if (returnType instanceof DemangledList list && list.size() > 0) {
|
||||
if (list.containsNull()) {
|
||||
DemangledDataType dt = new DemangledDataType(properties.mangled(),
|
||||
properties.originalDemangled(), DemangledDataType.UNDEFINED);
|
||||
dt.incrementPointerLevels();
|
||||
function.setReturnType(dt);
|
||||
}
|
||||
else {
|
||||
SwiftTuple tuple = new SwiftTuple(properties.mangled(),
|
||||
properties.originalDemangled(), list, typeMetadata, demangler);
|
||||
function.setReturnType(tuple);
|
||||
}
|
||||
}
|
||||
|
||||
return function;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftDataTypeUtils;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Getter} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftGetterNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled demangled = null;
|
||||
String name = "get_";
|
||||
String callingConvention = CompilerSpec.CALLING_CONVENTION_default;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Subscript:
|
||||
demangled = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case Variable:
|
||||
demangled = child.demangle(demangler, typeMetadata);
|
||||
if (child.hasChild(SwiftDemangledNodeKind.Class)) {
|
||||
callingConvention = CompilerSpec.CALLING_CONVENTION_thiscall;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (demangled instanceof DemangledFunction function) {
|
||||
function.setName(name + function.getName());
|
||||
function.setCallingConvention(callingConvention);
|
||||
return function;
|
||||
}
|
||||
if (demangled instanceof DemangledVariable variable) {
|
||||
SwiftFunction function =
|
||||
new SwiftFunction(properties.mangled(), properties.originalDemangled(),
|
||||
name + variable.getName(), variable.getNamespace(), callingConvention);
|
||||
function.addParameters(SwiftDataTypeUtils.extractParameters(variable.getNamespace()));
|
||||
function.setReturnType(variable.getDataType());
|
||||
return function;
|
||||
}
|
||||
return getUnknown();
|
||||
}
|
||||
}
|
|
@ -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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftPrimitive;
|
||||
import ghidra.program.model.data.DataUtilities;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Global} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftGlobalNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled demangled = null;
|
||||
Demangled suffix = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case GenericSpecialization:
|
||||
case MergedFunction:
|
||||
case ObjCAttribute:
|
||||
continue;
|
||||
case Suffix:
|
||||
suffix = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
demangled = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (demangled == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
if (suffix != null && !(demangled instanceof SwiftPrimitive) &&
|
||||
DataUtilities.isValidDataTypeName(suffix.getName())) {
|
||||
// Some suffix names aren't renderable, so validate them
|
||||
demangled.setName(demangled.getName() + suffix.getName());
|
||||
}
|
||||
return demangled;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#GlobalVariableOnceDeclList} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftGlobalVariableOnceDeclListNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
List<Demangled> elements = new ArrayList<>();
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
elements.add(child.demangle(demangler, typeMetadata));
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new DemangledList(elements);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#GlobalVariableOnceFunction} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftGlobalVariableOnceFunctionNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled namespace = null;
|
||||
DemangledList names = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case GlobalVariableOnceDeclList:
|
||||
Demangled demangled = child.demangle(demangler, typeMetadata);
|
||||
if (demangled instanceof DemangledList list) {
|
||||
names = list;
|
||||
}
|
||||
break;
|
||||
case Structure:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
StringBuilder name = new StringBuilder("one_time_init");
|
||||
if (names != null) {
|
||||
if (!names.isEmpty()) {
|
||||
name.append("_for");
|
||||
}
|
||||
for (Demangled entry : names) {
|
||||
name.append("_" + entry.getDemangledName());
|
||||
}
|
||||
}
|
||||
return new SwiftFunction(properties.mangled(), properties.originalDemangled(),
|
||||
name.toString(), namespace, CompilerSpec.CALLING_CONVENTION_default);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#InOut} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftInOutNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled demangled = demangleFirstChild(demangler, typeMetadata);
|
||||
if (demangled instanceof DemangledDataType type) {
|
||||
type.incrementPointerLevels();
|
||||
}
|
||||
return demangled;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Initializer} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftInitializerNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Variable:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "init";
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
return new SwiftFunction(properties.mangled(), properties.originalDemangled(), name,
|
||||
namespace, CompilerSpec.CALLING_CONVENTION_default);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#LabelList} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftLabelListNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
List<Demangled> elements = new ArrayList<>();
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
elements.add(child.demangle(demangler, typeMetadata));
|
||||
break;
|
||||
case FirstElementMarker:
|
||||
elements.add(new DemangledUnknown(properties.mangled(),
|
||||
properties.originalDemangled(), ""));
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new DemangledList(elements);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#LazyProtocolWitnessTableAccessor} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftLazyProtocolWitnessTableAccessorNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Type:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "lazy_protocol_witness_table_accessor";
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
return new SwiftFunction(properties.mangled(), properties.originalDemangled(), name,
|
||||
namespace, CompilerSpec.CALLING_CONVENTION_default);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#LocalDeclName} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftLocalDeclNameNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Long number = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
name = child.getText();
|
||||
break;
|
||||
case Number:
|
||||
try {
|
||||
number = Long.decode(child.getIndex());
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
throw new DemangledException(e);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
if (number != null) {
|
||||
name += "#" + (number + 1);
|
||||
}
|
||||
return new DemangledLabel(properties.mangled(), properties.originalDemangled(), name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftDataTypeUtils;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#ModifyAccessor} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftModifyAccessorNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled demangled = null;
|
||||
String name = "modify_";
|
||||
String callingConvention = CompilerSpec.CALLING_CONVENTION_thiscall;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Subscript:
|
||||
demangled = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case Variable:
|
||||
demangled = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (demangled instanceof DemangledFunction function) {
|
||||
function.setName(name + function.getName());
|
||||
function.setCallingConvention(callingConvention);
|
||||
return function;
|
||||
}
|
||||
if (demangled instanceof DemangledVariable variable) {
|
||||
SwiftFunction function =
|
||||
new SwiftFunction(properties.mangled(), properties.originalDemangled(),
|
||||
name + variable.getName(), variable.getNamespace(), callingConvention);
|
||||
function.addParameters(SwiftDataTypeUtils.extractParameters(variable));
|
||||
return function;
|
||||
}
|
||||
return getUnknown();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,378 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.nodes.generic.*;
|
||||
|
||||
/**
|
||||
* A single Swift demangled symbol tree node
|
||||
*/
|
||||
public abstract class SwiftNode {
|
||||
|
||||
protected NodeProperties properties;
|
||||
private SwiftNode parent;
|
||||
private List<SwiftNode> children = new ArrayList<>();
|
||||
private boolean childSkipped = false;
|
||||
|
||||
/**
|
||||
* Represents {@link SwiftNode} properties
|
||||
*
|
||||
* @param kind The {@link SwiftDemangledNodeKind kind} of {@link SwiftNode}
|
||||
* @param text The text attribute, or null if it does not exist
|
||||
* @param index The index attribute, or null if it does not exist
|
||||
* @param depth The depth of the {@link SwiftNode} in the demangled symbol tree (root depth is
|
||||
* 0)
|
||||
* @param mangled The mangled string associated with this {@link SwiftNode}
|
||||
* @param originalDemangled The natively demangled string
|
||||
*/
|
||||
public record NodeProperties(SwiftDemangledNodeKind kind, String text, String index,
|
||||
int depth, String mangled, String originalDemangled) {}
|
||||
|
||||
/**
|
||||
* Gets a new {@link SwiftNode} with the given with the given {@link NodeProperties}
|
||||
*
|
||||
* @param props The {@link NodeProperties}
|
||||
* @return A {@link SwiftNode} with the given {@link NodeProperties}
|
||||
*/
|
||||
public static SwiftNode get(NodeProperties props) {
|
||||
SwiftNode node = switch (props.kind()) {
|
||||
case Allocator -> new SwiftAllocatorNode();
|
||||
case AnonymousDescriptor -> new SwiftGenericDescriptorNode();
|
||||
case ArgumentTuple -> new SwiftGenericPassthroughNode();
|
||||
case BoundGenericStructure -> new SwiftBoundGenericStructureNode();
|
||||
case BuiltinTypeName -> new SwiftBuiltinTypeNameNode();
|
||||
case Class -> new SwiftClassNode();
|
||||
case Constructor -> new SwiftConstructorNode();
|
||||
case Deallocator -> new SwiftDeallocatorNode();
|
||||
case DefaultArgumentInitializer -> new SwiftGenericPassthroughNode();
|
||||
case DependentGenericParamType -> new SwiftDependentGenericParamTypeNode();
|
||||
case DependentGenericType -> new SwiftDependentGenericTypeNode();
|
||||
case Destructor -> new SwiftDestructorNode();
|
||||
case DispatchThunk -> new SwiftGenericPassthroughNode();
|
||||
case Enum -> new SwiftEnumNode();
|
||||
case Extension -> new ghidra.app.util.demangler.swift.nodes.SwiftExtensionNode();
|
||||
case Function -> new SwiftFunctionNode();
|
||||
case FunctionType -> new SwiftFunctionTypeNode();
|
||||
case GenericSpecialization -> new SwiftGenericTextNode();
|
||||
case Getter -> new SwiftGetterNode();
|
||||
case Global -> new SwiftGlobalNode();
|
||||
case GlobalVariableOnceDeclList -> new SwiftGlobalVariableOnceDeclListNode();
|
||||
case GlobalVariableOnceFunction -> new SwiftGlobalVariableOnceFunctionNode();
|
||||
case Identifier -> new SwiftGenericTextNode();
|
||||
case InfixOperator -> new SwiftGenericTextNode();
|
||||
case Initializer -> new SwiftInitializerNode();
|
||||
case InOut -> new SwiftInOutNode();
|
||||
case LabelList -> new SwiftLabelListNode();
|
||||
case LazyProtocolWitnessTableAccessor -> new SwiftLazyProtocolWitnessTableAccessorNode();
|
||||
case LocalDeclName -> new SwiftLocalDeclNameNode();
|
||||
case MergedFunction -> new SwiftGenericPassthroughNode();
|
||||
case ModifyAccessor -> new SwiftModifyAccessorNode();
|
||||
case Module -> new SwiftGenericTextNode();
|
||||
case ModuleDescriptor -> new SwiftGenericDescriptorNode();
|
||||
case NominalTypeDescriptor -> new SwiftGenericDescriptorNode();
|
||||
case Number -> new SwiftGenericIndexNode();
|
||||
case ObjCAttribute -> new SwiftGenericTextNode();
|
||||
case OutlinedConsume -> new SwiftOutlinedConsumeNode();
|
||||
case OutlinedCopy -> new SwiftOutlinedCopyNode();
|
||||
case Owned -> new SwiftGenericPassthroughNode();
|
||||
case PrivateDeclName -> new SwiftPrivateDeclNameNode();
|
||||
case Protocol -> new SwiftProtocolNode();
|
||||
case ProtocolConformance -> new SwiftProtocolConformanceNode();
|
||||
case ProtocolConformanceDescriptor -> new SwiftGenericDescriptorNode();
|
||||
case ProtocolDescriptor -> new SwiftGenericDescriptorNode();
|
||||
case ProtocolWitness -> new SwiftGenericPassthroughNode();
|
||||
case ReflectionMetadataBuiltinDescriptor -> new SwiftGenericDescriptorNode();
|
||||
case ReflectionMetadataFieldDescriptor -> new SwiftGenericDescriptorNode();
|
||||
case ReturnType -> new SwiftGenericPassthroughNode();
|
||||
case Setter -> new SwiftSetterNode();
|
||||
case Static -> new SwiftGenericPassthroughNode();
|
||||
case Structure -> new SwiftStructureNode();
|
||||
case Subscript -> new SwiftSubscriptNode();
|
||||
case Suffix -> new SwiftGenericTextNode();
|
||||
case Tuple -> new SwiftTupleNode();
|
||||
case TupleElement -> new SwiftTupleElementNode();
|
||||
case TupleElementName -> new SwiftGenericTextNode();
|
||||
case Type -> new SwiftTypeNode();
|
||||
case TypeAlias -> new SwiftTypeAliasNode();
|
||||
case TypeList -> new SwiftTypeListNode();
|
||||
case TypeMetadataAccessFunction -> new SwiftTypeMetadataAccessFunctionNode();
|
||||
case UnsafeMutableAddressor -> new SwiftUnsafeMutableAddressorNode();
|
||||
case Variable -> new SwiftVariableNode();
|
||||
default -> new SwiftUnsupportedNode(props.kind().toString(), props);
|
||||
};
|
||||
node.properties = props;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Demangles this {@link SwiftNode}
|
||||
*
|
||||
* @param demangler The {@link SwiftDemangler}
|
||||
* @param typeMetadata The {@link SwiftTypeMetadata}, or null if it is not known
|
||||
* @return The demangled {@link SwiftNode}
|
||||
* @throws DemangledException if a problem occurred
|
||||
*/
|
||||
public abstract Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException;
|
||||
|
||||
/**
|
||||
* Gets the {@link SwiftDemangledNodeKind kind} of {@link SwiftNode}
|
||||
*
|
||||
* @return The {@link SwiftDemangledNodeKind kind} of {@link SwiftNode}
|
||||
*/
|
||||
public SwiftDemangledNodeKind getKind() {
|
||||
return properties.kind();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "text" property
|
||||
*
|
||||
* @return The "text" attribute, or null if it does not exist
|
||||
*/
|
||||
public String getText() {
|
||||
return properties.text();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "index" property
|
||||
*
|
||||
* @return The "index" attribute, or null if it does not exist
|
||||
*/
|
||||
public String getIndex() {
|
||||
return properties.index();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the depth of the {@link SwiftNode} in the demangled symbol tree (root depth is 0)
|
||||
*
|
||||
* @return The depth of the {@link SwiftNode} in the demangled symbol tree (root depth is 0)
|
||||
*/
|
||||
public int getDepth() {
|
||||
return properties.depth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parent {@link SwiftNode}
|
||||
*
|
||||
* @return The parent {@link SwiftNode}, or null if this is the root {@link SwiftNode}
|
||||
*/
|
||||
public SwiftNode getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent {@link SwiftNode}
|
||||
*
|
||||
* @param parent The parent {@link SwiftNode}
|
||||
*/
|
||||
public void setParent(SwiftNode parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link List} of child {@link SwiftNode}s
|
||||
*
|
||||
* @return The {@link List} of child {@link SwiftNode} (original, not a copy)
|
||||
*/
|
||||
public List<SwiftNode> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks down the tree rooted at this {@link SwiftNode}, returning true if the given condition
|
||||
* is met on any {@link SwiftNode} encountered
|
||||
*
|
||||
* @param predicate The condition to test for
|
||||
* @return True if the given condition is true on any {@link SwiftNode} encountered; otherwise,
|
||||
* false
|
||||
*/
|
||||
public boolean walkAndTest(Predicate<SwiftNode> predicate) {
|
||||
if (predicate.test(this)) {
|
||||
return true;
|
||||
}
|
||||
for (SwiftNode child : children) {
|
||||
if (child.walkAndTest(predicate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the {@link SwiftNode} has any direct children of the given
|
||||
* {@link SwiftDemangledNodeKind kind}
|
||||
*
|
||||
* @param childKind The {@link SwiftDemangledNodeKind kind} of child to check for
|
||||
* @return True if the {@link SwiftNode} has any direct children of the given
|
||||
* {@link SwiftDemangledNodeKind kind}; otherwise false
|
||||
*/
|
||||
public boolean hasChild(SwiftDemangledNodeKind childKind) {
|
||||
return children.stream().anyMatch(child -> child.getKind().equals(childKind));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first direct child {@link SwiftNode} of the given
|
||||
* {@link SwiftDemangledNodeKind kind}
|
||||
*
|
||||
* @param childKind The {@link SwiftDemangledNodeKind kind} of child to get
|
||||
* @return The first direct child {@link SwiftNode} of the given
|
||||
* {@link SwiftDemangledNodeKind kind}, or null if one could not be found
|
||||
*/
|
||||
public SwiftNode getChild(SwiftDemangledNodeKind childKind) {
|
||||
return children.stream()
|
||||
.filter(child -> child.getKind().equals(childKind))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first ancestor {@link SwiftNode} of the given kind(s)
|
||||
*
|
||||
* @param ancestorKinds The ancestor kinds
|
||||
* @return The first ancestor {@link SwiftNode} of the given kind
|
||||
*/
|
||||
public SwiftNode getFirstAncestor(SwiftDemangledNodeKind... ancestorKinds) {
|
||||
if (ancestorKinds != null && ancestorKinds.length > 0) {
|
||||
for (SwiftNode p = parent; p != null; p = p.getParent()) {
|
||||
for (SwiftDemangledNodeKind ancestorKind : ancestorKinds) {
|
||||
if (p.getKind().equals(ancestorKind)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this {@link SwiftNode} skipped processing a child during the demangling process.
|
||||
* Used to identify and/or debug missing implementations.
|
||||
*
|
||||
* @param child The skipped child {@link SwiftNode}
|
||||
*/
|
||||
public void skip(SwiftNode child) {
|
||||
childSkipped = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this {@link SwiftNode} skipped processing any children during the
|
||||
* demangling process
|
||||
*
|
||||
* @return True if a child {@link SwiftNode} was skipped; otherwise, false
|
||||
*/
|
||||
public boolean childWasSkipped() {
|
||||
return childSkipped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new {@link DemangledUnknown} created from this {@link SwiftNode}
|
||||
*
|
||||
* @return A new {@link DemangledUnknown} created from this {@link SwiftNode}
|
||||
*/
|
||||
public DemangledUnknown getUnknown() {
|
||||
return new DemangledUnknown(properties.mangled(), properties.originalDemangled(),
|
||||
properties.originalDemangled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins the first {@link Demangled} with the second. The name of the first will become the
|
||||
* top-level namespace of the second.
|
||||
*
|
||||
* @param a The first {@link Demangled} to join
|
||||
* @param b The second {@link Demangled} to join
|
||||
* @return The joined {@link Demangled}s
|
||||
*/
|
||||
public static Demangled join(Demangled a, Demangled b) {
|
||||
if (a == null) {
|
||||
return b;
|
||||
}
|
||||
if (b == null) {
|
||||
return a;
|
||||
}
|
||||
Demangled topNamespace = b;
|
||||
while (topNamespace.getNamespace() != null) {
|
||||
topNamespace = topNamespace.getNamespace();
|
||||
}
|
||||
topNamespace.setNamespace(a);
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link SwiftNode} to a string
|
||||
*
|
||||
* @param node The {@link SwiftNode} to convert to a string
|
||||
* @param recurse True if the {@link SwiftNode} should be recursed; otherwise, false
|
||||
* @return The given {@link SwiftNode} in string form
|
||||
*/
|
||||
public static String toString(SwiftNode node, boolean recurse) {
|
||||
StringBuilder sb = new StringBuilder(node.toString());
|
||||
if (recurse) {
|
||||
sb.append("\n");
|
||||
for (SwiftNode child : node.getChildren()) {
|
||||
sb.append(toString(child, true));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" ".repeat(properties.depth() * 2));
|
||||
sb.append("kind=" + properties.kind());
|
||||
if (properties.text() != null) {
|
||||
sb.append(", text=\"" + properties.text() + "\"");
|
||||
}
|
||||
if (properties.index() != null) {
|
||||
sb.append(", index=" + properties.index() + "");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Demangles the first child {@link SwiftNode}, if it exists
|
||||
*
|
||||
* @param demangler The {@link SwiftDemangler}
|
||||
* @param typeMetadata The {@link SwiftTypeMetadata}, or null if it is not known
|
||||
* @return The demangled first child {@link SwiftNode}
|
||||
* @throws DemangledException if there are no children or another problem occurred
|
||||
*/
|
||||
protected Demangled demangleFirstChild(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled first = null;
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
SwiftNode child = children.get(i);
|
||||
if (i == 0) {
|
||||
first = child.demangle(demangler, typeMetadata);
|
||||
}
|
||||
else {
|
||||
child.skip(child);
|
||||
}
|
||||
}
|
||||
if (first == null) {
|
||||
throw new DemangledException("No children");
|
||||
}
|
||||
return first;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#OutlinedConsume} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftOutlinedConsumeNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled type = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SwiftFunction function =
|
||||
new SwiftFunction(properties.mangled(), properties.originalDemangled(),
|
||||
"outlined_consume", null, CompilerSpec.CALLING_CONVENTION_default);
|
||||
if (type instanceof DemangledDataType dt) {
|
||||
function.addParameter(new DemangledParameter(dt));
|
||||
}
|
||||
return function;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#OutlinedCopy} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftOutlinedCopyNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled type = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SwiftFunction function =
|
||||
new SwiftFunction(properties.mangled(), properties.originalDemangled(),
|
||||
"outlined_copy", null, CompilerSpec.CALLING_CONVENTION_default);
|
||||
if (type instanceof DemangledDataType dt) {
|
||||
function.addParameter(new DemangledParameter(dt));
|
||||
}
|
||||
return function;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#PrivateDeclName} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftPrivateDeclNameNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
if (namespace == null) {
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
}
|
||||
else {
|
||||
name = child.getText();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
if (namespace == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
name = namespace.getNamespace().getName();
|
||||
namespace = null;
|
||||
}
|
||||
DemangledUnknown demangled =
|
||||
new DemangledUnknown(properties.mangled(), properties.originalDemangled(), name);
|
||||
demangled.setNamespace(namespace);
|
||||
return demangled;
|
||||
}
|
||||
}
|
|
@ -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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#ProtocolConformance} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftProtocolConformanceNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled type1 = null;
|
||||
Demangled type2 = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Module:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case Type:
|
||||
if (type1 == null) {
|
||||
type1 = child.demangle(demangler, typeMetadata);
|
||||
}
|
||||
else {
|
||||
type2 = child.demangle(demangler, typeMetadata);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type1 == null && type2 == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
DemangledUnknown demangled = new DemangledUnknown(properties.mangled(),
|
||||
properties.originalDemangled(), SwiftNode.join(type2, type1).getNamespaceString());
|
||||
demangled.setNamespace(namespace);
|
||||
return demangled;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Protocol} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftProtocolNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
name = child.getText();
|
||||
break;
|
||||
case Module:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
DemangledUnknown demangled =
|
||||
new DemangledUnknown(properties.mangled(), properties.originalDemangled(), name);
|
||||
demangled.setNamespace(namespace);
|
||||
return demangled;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftDataTypeUtils;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Setter} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftSetterNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled demangled = null;
|
||||
String name = "set_";
|
||||
String callingConvention = CompilerSpec.CALLING_CONVENTION_thiscall;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Subscript:
|
||||
demangled = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case Variable:
|
||||
demangled = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (demangled instanceof DemangledFunction function) {
|
||||
function.setName(name + function.getName());
|
||||
function.setCallingConvention(callingConvention);
|
||||
return function;
|
||||
}
|
||||
if (demangled instanceof DemangledVariable variable) {
|
||||
SwiftFunction function =
|
||||
new SwiftFunction(properties.mangled(), properties.originalDemangled(),
|
||||
name + variable.getName(), variable.getNamespace(), callingConvention);
|
||||
function.addParameters(SwiftDataTypeUtils.extractParameters(variable));
|
||||
return function;
|
||||
}
|
||||
return getUnknown();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.*;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Structure} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftStructureNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
Demangled privateDeclNamespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
name = child.getText();
|
||||
break;
|
||||
case PrivateDeclName:
|
||||
Demangled temp = child.demangle(demangler, typeMetadata);
|
||||
name = temp.getName();
|
||||
privateDeclNamespace = temp.getNamespace();
|
||||
break;
|
||||
case Class:
|
||||
case Module:
|
||||
case Structure:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
|
||||
String mangled = properties.mangled();
|
||||
String orig = properties.originalDemangled();
|
||||
if (SwiftDataTypeUtils.isSwiftNamespace(namespace)) {
|
||||
DemangledDataType type = switch (name) {
|
||||
case "Bool" -> new SwiftPrimitive(mangled, orig, DemangledDataType.BOOL);
|
||||
case "Int" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT);
|
||||
case "Int8" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT8);
|
||||
case "Int16" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT16);
|
||||
case "Int32" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT32);
|
||||
case "Int64" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT64);
|
||||
case "UInt" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT, true);
|
||||
case "UInt8" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT8, true);
|
||||
case "UInt16" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT16, true);
|
||||
case "UInt32" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT32, true);
|
||||
case "UInt64" -> new SwiftPrimitive(mangled, orig, DemangledDataType.INT64, true);
|
||||
case "Float" -> new SwiftPrimitive(mangled, orig, DemangledDataType.FLOAT);
|
||||
case "Float16" -> new SwiftPrimitive(mangled, orig, DemangledDataType.FLOAT2);
|
||||
case "Double" -> new SwiftPrimitive(mangled, orig, DemangledDataType.DOUBLE);
|
||||
case "Array" -> new SwiftArray(mangled, orig);
|
||||
case "Character" -> new SwiftCharacter(mangled, orig);
|
||||
case "String" -> new SwiftString(mangled, orig);
|
||||
default -> null;
|
||||
};
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
SwiftStructure struct = new SwiftStructure(mangled, orig, name,
|
||||
SwiftNode.join(namespace, privateDeclNamespace), typeMetadata, demangler);
|
||||
|
||||
// The structure has no fields, which behaves poorly in the decompiler. Give it one
|
||||
// undefined* field instead.
|
||||
if (struct.getFields().isEmpty()) {
|
||||
DemangledDataType undefined =
|
||||
new DemangledDataType(mangled, orig, DemangledDataType.UNDEFINED);
|
||||
undefined.incrementPointerLevels();
|
||||
struct.addField("unknown", null, undefined);
|
||||
}
|
||||
|
||||
return struct;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Subscript} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftSubscriptNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
Demangled type = null;
|
||||
Demangled labelList = null;
|
||||
String callingConvention = CompilerSpec.CALLING_CONVENTION_default;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Class:
|
||||
callingConvention = CompilerSpec.CALLING_CONVENTION_thiscall;
|
||||
// Fall through
|
||||
case Structure:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "subscript";
|
||||
break;
|
||||
case LabelList:
|
||||
labelList = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
SwiftFunction function = new SwiftFunction(properties.mangled(),
|
||||
properties.originalDemangled(), name, namespace, callingConvention);
|
||||
if (type instanceof DemangledFunction functionType) {
|
||||
function.setType(functionType, labelList);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#TupleElement} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftTupleElementNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled type = null;
|
||||
String name = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case TupleElementName:
|
||||
name = child.getText();
|
||||
break;
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
if (name != null && type instanceof DemangledDataType ddt) {
|
||||
DemangledVariable variable =
|
||||
new DemangledVariable(properties.mangled(), properties.originalDemangled(), name);
|
||||
variable.setDatatype(ddt);
|
||||
return variable;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Tuple} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftTupleNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
List<Demangled> elements = new ArrayList<>();
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case TupleElement:
|
||||
elements.add(child.demangle(demangler, typeMetadata));
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new DemangledList(elements);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#TypeAlias} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftTypeAliasNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
name = child.getText();
|
||||
break;
|
||||
case Module:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
DemangledDataType type =
|
||||
new DemangledDataType(properties.mangled(), properties.originalDemangled(), name);
|
||||
type.setNamespace(namespace);
|
||||
type.setClass();
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#TypeList} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftTypeListNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
List<Demangled> elements = new ArrayList<>();
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Type:
|
||||
elements.add(child.demangle(demangler, typeMetadata));
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new DemangledList(elements);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#TypeMetadataAccessFunction} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftTypeMetadataAccessFunctionNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Type:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "typeMetadataAccessor";
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
SwiftFunction function =
|
||||
new SwiftFunction(properties.mangled(), properties.originalDemangled(), name, namespace,
|
||||
CompilerSpec.CALLING_CONVENTION_default);
|
||||
if (namespace instanceof DemangledDataType type) {
|
||||
function.setReturnType(type);
|
||||
}
|
||||
return function;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Type} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftTypeNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
return demangleFirstChild(demangler, typeMetadata);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.datatypes.SwiftFunction;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#UnsafeMutableAddressor} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftUnsafeMutableAddressorNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Variable:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
name = "unsafeMutableAddressor";
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
return new SwiftFunction(properties.mangled(), properties.originalDemangled(), name,
|
||||
namespace, CompilerSpec.CALLING_CONVENTION_default);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Unsupported} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftUnsupportedNode extends SwiftNode {
|
||||
|
||||
private String originalKind;
|
||||
|
||||
/**
|
||||
* Create a new {@link SwiftUnsupportedNode} {@link SwiftNode}
|
||||
*
|
||||
* @param originalKind The original {@link SwiftDemangledNodeKind kind} of {@link SwiftNode} that is
|
||||
* not supported
|
||||
* @param props The {@link ghidra.app.util.demangler.swift.nodes.SwiftNode.NodeProperties}
|
||||
*/
|
||||
public SwiftUnsupportedNode(String originalKind, NodeProperties props) {
|
||||
this.originalKind = originalKind;
|
||||
this.properties = props;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata) {
|
||||
skip(this);
|
||||
return getUnknown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " (" + originalKind + ")";
|
||||
}
|
||||
}
|
|
@ -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.demangler.swift.nodes;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangledNodeKind;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
|
||||
/**
|
||||
* A {@link SwiftDemangledNodeKind#Variable} {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftVariableNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
String name = null;
|
||||
Demangled namespace = null;
|
||||
Demangled privateDeclNamespace = null;
|
||||
Demangled type = null;
|
||||
for (SwiftNode child : getChildren()) {
|
||||
switch (child.getKind()) {
|
||||
case Identifier:
|
||||
name = child.getText();
|
||||
break;
|
||||
case PrivateDeclName:
|
||||
Demangled temp = child.demangle(demangler, typeMetadata);
|
||||
name = temp.getName();
|
||||
privateDeclNamespace = temp.getNamespace();
|
||||
break;
|
||||
case Class:
|
||||
case Enum:
|
||||
case Extension:
|
||||
case Module:
|
||||
case Protocol:
|
||||
case Structure:
|
||||
namespace = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
case Type:
|
||||
type = child.demangle(demangler, typeMetadata);
|
||||
break;
|
||||
default:
|
||||
skip(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
return getUnknown();
|
||||
}
|
||||
DemangledVariable variable =
|
||||
new DemangledVariable(properties.mangled(), properties.originalDemangled(), name);
|
||||
if (type instanceof DemangledDataType ddt) {
|
||||
variable.setDatatype(ddt);
|
||||
}
|
||||
variable.setNamespace(SwiftNode.join(namespace, privateDeclNamespace));
|
||||
return variable;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes.generic;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftNode;
|
||||
|
||||
/**
|
||||
* A {@link SwiftNode} to represent a generic descriptor
|
||||
*/
|
||||
public class SwiftGenericDescriptorNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
Demangled demangled = demangleFirstChild(demangler, typeMetadata);
|
||||
return new DemangledLabel(properties.mangled(), properties.originalDemangled(),
|
||||
demangled.getNamespaceString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes.generic;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledLabel;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftNode;
|
||||
|
||||
/**
|
||||
* A {@link SwiftNode} that just contains an index
|
||||
*/
|
||||
public class SwiftGenericIndexNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata) {
|
||||
return new DemangledLabel(properties.mangled(), properties.originalDemangled(),
|
||||
getIndex());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes.generic;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftNode;
|
||||
|
||||
/**
|
||||
* A {@link SwiftNode} that simply passes through to its child {@link SwiftNode}
|
||||
*/
|
||||
public class SwiftGenericPassthroughNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata)
|
||||
throws DemangledException {
|
||||
return demangleFirstChild(demangler, typeMetadata);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* ###
|
||||
* 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.demangler.swift.nodes.generic;
|
||||
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadata;
|
||||
import ghidra.app.util.demangler.Demangled;
|
||||
import ghidra.app.util.demangler.DemangledLabel;
|
||||
import ghidra.app.util.demangler.swift.SwiftDemangler;
|
||||
import ghidra.app.util.demangler.swift.nodes.SwiftNode;
|
||||
|
||||
/**
|
||||
* A {@link SwiftNode} that just contains text
|
||||
*/
|
||||
public class SwiftGenericTextNode extends SwiftNode {
|
||||
|
||||
@Override
|
||||
public Demangled demangle(SwiftDemangler demangler, SwiftTypeMetadata typeMetadata) {
|
||||
return new DemangledLabel(properties.mangled(), properties.originalDemangled(),
|
||||
getText());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,705 @@
|
|||
/* ###
|
||||
* 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.demangler.swift;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.app.util.demangler.DemangledFunction;
|
||||
import ghidra.app.util.demangler.DemangledStructure;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link SwiftDemangler}. Requires Swift to be installed on the test system.
|
||||
* If it is not, these tests will be skipped.
|
||||
*/
|
||||
public class SwiftDemanglerTest extends AbstractGenericTest {
|
||||
|
||||
private SwiftDemangler demangler;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
demangler = new SwiftDemangler();
|
||||
|
||||
// Ghidra does not ship the native Swift demangler binary, so it may not be present to run
|
||||
// these tests. In this scenario, we just want these tests skipped (as opposed to failing).
|
||||
try {
|
||||
new SwiftNativeDemangler(new SwiftDemanglerOptions().getSwiftDir());
|
||||
}
|
||||
catch (IOException e) {
|
||||
assumeNoException(e); // skip test, don't fail
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionAndTypes() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Function
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="testJunitFunctionAndTypes"
|
||||
kind=LabelList
|
||||
kind=FirstElementMarker
|
||||
kind=Identifier, text="label2"
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=Identifier, text="label14"
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=FirstElementMarker
|
||||
kind=Type
|
||||
kind=FunctionType
|
||||
kind=ArgumentTuple
|
||||
kind=Type
|
||||
kind=Tuple
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=InOut
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int8"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int16"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int32"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int64"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="UInt"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="UInt8"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="UInt16"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="UInt32"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="UInt64"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Float"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Float"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Double"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Double"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="String"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=BoundGenericStructure
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Array"
|
||||
kind=TypeList
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Bool"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Character"
|
||||
kind=ReturnType
|
||||
kind=Type
|
||||
kind=Tuple
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Float"
|
||||
SwiftDemanglerTest.testJunitFunctionAndTypes(_: inout Swift.Int, label2: Swift.Int8, _: Swift.Int16, _: Swift.Int32, _: Swift.Int64, _: Swift.UInt, _: Swift.UInt8, _: Swift.UInt16, _: Swift.UInt32, _: Swift.UInt64, _: Swift.Float, _: Swift.Float, _: Swift.Double, label14: Swift.Double, _: Swift.String, _: [Swift.Int], _: Swift.Bool, _: Swift.Character) -> (Swift.Int, Swift.Float)
|
||||
**********************************************************************/
|
||||
String mangled =
|
||||
"_$s18SwiftDemanglerTest25testJunitFunctionAndTypes_6label2___________7label14____Si_SftSiz_s4Int8Vs5Int16Vs5Int32Vs5Int64VSus5UInt8Vs6UInt16Vs6UInt32Vs6UInt64VS2fS2dSSSaySiGSbSJtF";
|
||||
String demangled =
|
||||
"struct tuple2 default SwiftDemanglerTest::testJunitFunctionAndTypes(int *,__int8 label2,__int16,__int32,__int64,unsigned int,unsigned __int8,unsigned __int16,unsigned __int32,unsigned __int64,float,float,double,double label14,struct Swift::String,Swift::Array<int>[],bool,struct Swift::Character)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
|
||||
if (!(function.getReturnType() instanceof DemangledStructure struct)) {
|
||||
throw new AssertException("Demangled return type is not a structure");
|
||||
}
|
||||
assertEquals(struct.getFields().size(), 2);
|
||||
assertEquals(struct.getFields().get(0).type().toString(), "int");
|
||||
assertEquals(struct.getFields().get(1).type().toString(), "float");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureAllocator() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Allocator
|
||||
kind=Structure
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyStructure"
|
||||
kind=LabelList
|
||||
kind=Identifier, text="label1"
|
||||
kind=Type
|
||||
kind=FunctionType
|
||||
kind=ArgumentTuple
|
||||
kind=Type
|
||||
kind=Tuple
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=ReturnType
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyStructure"
|
||||
SwiftDemanglerTest.MyStructure.init(label1: Swift.Int) -> SwiftDemanglerTest.MyStructure
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest11MyStructureV6label1ACSi_tcfC";
|
||||
String demangled =
|
||||
"struct SwiftDemanglerTest::MyStructure default SwiftDemanglerTest::MyStructure::init(int label1)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureFunction() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Function
|
||||
kind=Structure
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyStructure"
|
||||
kind=Identifier, text="myMethod"
|
||||
kind=LabelList
|
||||
kind=Identifier, text="label1"
|
||||
kind=Identifier, text="label2"
|
||||
kind=Type
|
||||
kind=FunctionType
|
||||
kind=ArgumentTuple
|
||||
kind=Type
|
||||
kind=Tuple
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=ReturnType
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
SwiftDemanglerTest.MyStructure.myMethod(label1: Swift.Int, label2: Swift.Int) -> Swift.Int
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest11MyStructureV8myMethod6label16label2S2i_SitF";
|
||||
String demangled =
|
||||
"int default SwiftDemanglerTest::MyStructure::myMethod(int label1,int label2,struct SwiftDemanglerTest::MyStructure)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureGetter() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Getter
|
||||
kind=Variable
|
||||
kind=Structure
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyStructure"
|
||||
kind=Identifier, text="z"
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
SwiftDemanglerTest.MyStructure.z.getter : Swift.Int
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest11MyStructureV1zSivg";
|
||||
String demangled =
|
||||
"int default SwiftDemanglerTest::MyStructure::get_z(struct SwiftDemanglerTest::MyStructure)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureSetter() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Setter
|
||||
kind=Variable
|
||||
kind=Structure
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyStructure"
|
||||
kind=Identifier, text="z"
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
SwiftDemanglerTest.MyStructure.z.setter : Swift.Int
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest11MyStructureV1zSivs";
|
||||
String demangled = "__thiscall SwiftDemanglerTest::MyStructure::set_z(int)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureSubscriptGetter() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Getter
|
||||
kind=Subscript
|
||||
kind=Structure
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyStructure"
|
||||
kind=LabelList
|
||||
kind=Type
|
||||
kind=FunctionType
|
||||
kind=ArgumentTuple
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=ReturnType
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
SwiftDemanglerTest.MyStructure.subscript.getter : (Swift.Int) -> Swift.Int
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest11MyStructureVyS2icig";
|
||||
String demangled =
|
||||
"int default SwiftDemanglerTest::MyStructure::get_subscript(int,struct SwiftDemanglerTest::MyStructure)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureSubscriptSetter() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Setter
|
||||
kind=Subscript
|
||||
kind=Structure
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyStructure"
|
||||
kind=LabelList
|
||||
kind=Type
|
||||
kind=FunctionType
|
||||
kind=ArgumentTuple
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=ReturnType
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
SwiftDemanglerTest.MyStructure.subscript.setter : (Swift.Int) -> Swift.Int
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest11MyStructureVyS2icis";
|
||||
String demangled = "int __thiscall SwiftDemanglerTest::MyStructure::set_subscript(int)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassTypeMetadataAccessor() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=TypeMetadataAccessFunction
|
||||
kind=Type
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
type metadata accessor for SwiftDemanglerTest.MyClass
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest7MyClassCMa";
|
||||
String demangled =
|
||||
"class SwiftDemanglerTest::MyClass * default SwiftDemanglerTest::MyClass::typeMetadataAccessor(void)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassAllocator() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Allocator
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
kind=LabelList
|
||||
kind=Identifier, text="label1"
|
||||
kind=Type
|
||||
kind=FunctionType
|
||||
kind=ArgumentTuple
|
||||
kind=Type
|
||||
kind=Tuple
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=ReturnType
|
||||
kind=Type
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
SwiftDemanglerTest.MyClass.__allocating_init(label1: Swift.Int) -> SwiftDemanglerTest.MyClass
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest7MyClassC6label1ACSi_tcfC";
|
||||
String demangled =
|
||||
"class SwiftDemanglerTest::MyClass * __thiscall SwiftDemanglerTest::MyClass::__allocating_init(int label1)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassConstructor() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Constructor
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
kind=LabelList
|
||||
kind=Identifier, text="label1"
|
||||
kind=Type
|
||||
kind=FunctionType
|
||||
kind=ArgumentTuple
|
||||
kind=Type
|
||||
kind=Tuple
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=ReturnType
|
||||
kind=Type
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
SwiftDemanglerTest.MyClass.init(label1: Swift.Int) -> SwiftDemanglerTest.MyClass
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest7MyClassC6label1ACSi_tcfc";
|
||||
String demangled =
|
||||
"class SwiftDemanglerTest::MyClass * __thiscall SwiftDemanglerTest::MyClass::init(int label1)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassFunction() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Function
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
kind=Identifier, text="myMethod"
|
||||
kind=LabelList
|
||||
kind=Identifier, text="label1"
|
||||
kind=Identifier, text="label2"
|
||||
kind=Type
|
||||
kind=FunctionType
|
||||
kind=ArgumentTuple
|
||||
kind=Type
|
||||
kind=Tuple
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=ReturnType
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
SwiftDemanglerTest.MyClass.myMethod(label1: Swift.Int, label2: Swift.Int) -> Swift.Int
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest7MyClassC8myMethod6label16label2S2i_SitF";
|
||||
String demangled =
|
||||
"int __thiscall SwiftDemanglerTest::MyClass::myMethod(int label1,int label2)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassGetter() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Getter
|
||||
kind=Variable
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
kind=Identifier, text="z"
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
SwiftDemanglerTest.MyClass.z.getter : Swift.Int
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest7MyClassC1zSivg";
|
||||
String demangled =
|
||||
"int __thiscall SwiftDemanglerTest::MyClass::get_z(class SwiftDemanglerTest::MyClass *)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassSetter() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Setter
|
||||
kind=Variable
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
kind=Identifier, text="z"
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
SwiftDemanglerTest.MyClass.z.setter : Swift.Int
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest7MyClassC1zSivs";
|
||||
String demangled = "__thiscall SwiftDemanglerTest::MyClass::set_z(int)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassModifyAccessor() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=ModifyAccessor
|
||||
kind=Variable
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
kind=Identifier, text="z"
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
SwiftDemanglerTest.MyClass.z.modify : Swift.Int
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest7MyClassC1zSivM";
|
||||
String demangled = "__thiscall SwiftDemanglerTest::MyClass::modify_z(int)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassDeallocator() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Deallocator
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
SwiftDemanglerTest.MyClass.__deallocating_deinit
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest7MyClassCfD";
|
||||
String demangled = "__thiscall SwiftDemanglerTest::MyClass::__deallocating_init(void)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassDestructor() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Destructor
|
||||
kind=Class
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyClass"
|
||||
SwiftDemanglerTest.MyClass.deinit
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest7MyClassCfd";
|
||||
String demangled =
|
||||
"class SwiftDemanglerTest::MyClass * __thiscall SwiftDemanglerTest::MyClass::deinit(void)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnumFunction() throws Exception {
|
||||
/*-********************************************************************
|
||||
kind=Global
|
||||
kind=Function
|
||||
kind=Enum
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyAssociatedEnum"
|
||||
kind=Identifier, text="myMethod"
|
||||
kind=LabelList
|
||||
kind=Identifier, text="label1"
|
||||
kind=Type
|
||||
kind=FunctionType
|
||||
kind=ArgumentTuple
|
||||
kind=Type
|
||||
kind=Tuple
|
||||
kind=TupleElement
|
||||
kind=Type
|
||||
kind=Structure
|
||||
kind=Module, text="Swift"
|
||||
kind=Identifier, text="Int"
|
||||
kind=ReturnType
|
||||
kind=Type
|
||||
kind=Enum
|
||||
kind=Module, text="SwiftDemanglerTest"
|
||||
kind=Identifier, text="MyAssociatedEnum"
|
||||
SwiftDemanglerTest.MyAssociatedEnum.myMethod(label1: Swift.Int) -> SwiftDemanglerTest.MyAssociatedEnum
|
||||
**********************************************************************/
|
||||
String mangled = "_$s18SwiftDemanglerTest16MyAssociatedEnumO8myMethod6label1ACSi_tF";
|
||||
String demangled =
|
||||
"struct SwiftDemanglerTest::MyAssociatedEnum default SwiftDemanglerTest::MyAssociatedEnum::myMethod(int label1,struct SwiftDemanglerTest::MyAssociatedEnum,undefined)";
|
||||
|
||||
if (!(demangler.demangle(mangled) instanceof DemangledFunction function)) {
|
||||
throw new AssertException("Demangled object is not a function");
|
||||
}
|
||||
assertEquals(demangled, function.toString());
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ data/languages/AARCH64_AMXext.sinc||GHIDRA||||END|
|
|||
data/languages/AARCH64_AppleSilicon.slaspec||GHIDRA||||END|
|
||||
data/languages/AARCH64_base_PACoptions.sinc||GHIDRA||||END|
|
||||
data/languages/AARCH64_ilp32.cspec||GHIDRA||||END|
|
||||
data/languages/AARCH64_swift.cspec||GHIDRA||||END|
|
||||
data/languages/AARCH64_win.cspec||GHIDRA||||END|
|
||||
data/languages/AARCH64base.sinc||GHIDRA||||END|
|
||||
data/languages/AARCH64instructions.sinc||GHIDRA||||END|
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
<constraint primary="16777228" processor="AARCH64" endian="little" size="64" variant="AppleSilicon" />
|
||||
<constraint primary="33554444" processor="AARCH64" endian="little" size="32" variant="ilp32" />
|
||||
</constraint>
|
||||
<constraint loader="Mac OS X Mach-O" compilerSpecID="swift">
|
||||
<constraint primary="16777228" secondary="swift" processor="AARCH64" endian="little" size="64" variant="AppleSilicon" />
|
||||
</constraint>
|
||||
<constraint loader="DYLD Cache" compilerSpecID="default">
|
||||
<constraint primary="AARCH64" processor="AARCH64" endian="little" size="64" variant="AppleSilicon" />
|
||||
<constraint primary="ARM64_32" processor="AARCH64" endian="little" size="32" variant="ilp32" />
|
||||
|
|
393
Ghidra/Processors/AARCH64/data/languages/AARCH64_swift.cspec
Normal file
393
Ghidra/Processors/AARCH64/data/languages/AARCH64_swift.cspec
Normal file
|
@ -0,0 +1,393 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<compiler_spec>
|
||||
<data_organization>
|
||||
<absolute_max_alignment value="0" />
|
||||
<machine_alignment value="4" />
|
||||
<default_alignment value="2" />
|
||||
<default_pointer_alignment value="8" />
|
||||
<pointer_size value="8" />
|
||||
<wchar_size value="4" />
|
||||
<short_size value="2" />
|
||||
<integer_size value="8" />
|
||||
<long_size value="8" />
|
||||
<long_long_size value="8" />
|
||||
<float_size value="4" />
|
||||
<double_size value="8" />
|
||||
<long_double_size value="8" />
|
||||
<size_alignment_map>
|
||||
<entry size="1" alignment="1" />
|
||||
<entry size="2" alignment="2" />
|
||||
<entry size="4" alignment="4" />
|
||||
<entry size="8" alignment="8" />
|
||||
</size_alignment_map>
|
||||
</data_organization>
|
||||
|
||||
<global>
|
||||
<range space="ram"/>
|
||||
</global>
|
||||
|
||||
<stackpointer register="sp" space="ram"/>
|
||||
<funcptr align="4"/> <!-- Function pointers are word aligned and leastsig bit may encode otherstuff -->
|
||||
|
||||
<prefersplit style="inhalf">
|
||||
<register name="q0"/>
|
||||
<register name="q1"/>
|
||||
<register name="q2"/>
|
||||
<register name="q3"/>
|
||||
<register name="q4"/>
|
||||
<register name="q5"/>
|
||||
<register name="q6"/>
|
||||
<register name="q7"/>
|
||||
<register name="q8"/>
|
||||
<register name="q9"/>
|
||||
<register name="q10"/>
|
||||
<register name="q11"/>
|
||||
<register name="q12"/>
|
||||
<register name="q13"/>
|
||||
<register name="q14"/>
|
||||
<register name="q15"/>
|
||||
<register name="q16"/>
|
||||
<register name="q17"/>
|
||||
<register name="q18"/>
|
||||
<register name="q19"/>
|
||||
<register name="q20"/>
|
||||
<register name="q21"/>
|
||||
<register name="q22"/>
|
||||
<register name="q23"/>
|
||||
<register name="q24"/>
|
||||
<register name="q25"/>
|
||||
<register name="q26"/>
|
||||
<register name="q27"/>
|
||||
<register name="q28"/>
|
||||
<register name="q29"/>
|
||||
<register name="q30"/>
|
||||
</prefersplit>
|
||||
|
||||
<default_proto>
|
||||
<prototype name="__swiftcall" extrapop="0" stackshift="0">
|
||||
<!-- https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64 -->
|
||||
<input>
|
||||
<pentry minsize="8" maxsize="8" storage="hiddenret">
|
||||
<register name="x8"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d0"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d1"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d2"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d3"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d4"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d5"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d6"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d7"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x1"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x2"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x3"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x4"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x5"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x6"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x7"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="500" align="4">
|
||||
<addr offset="0" space="stack"/>
|
||||
</pentry>
|
||||
<rule>
|
||||
<datatype name="struct" minsize="9"/>
|
||||
<join/>
|
||||
</rule>
|
||||
</input>
|
||||
<output>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d0"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d1"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d2"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d3"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8">
|
||||
<register name="x0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8">
|
||||
<register name="x1"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8">
|
||||
<register name="x2"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8">
|
||||
<register name="x3"/>
|
||||
</pentry>
|
||||
<rule>
|
||||
<datatype name="homogeneous-float-aggregate"/>
|
||||
<join_per_primitive storage="float"/>
|
||||
</rule>
|
||||
<rule>
|
||||
<datatype name="float"/>
|
||||
<consume storage="float"/>
|
||||
</rule>
|
||||
<rule>
|
||||
<datatype name="any" minsize="1" maxsize="32"/>
|
||||
<join/>
|
||||
</rule>
|
||||
<rule>
|
||||
<datatype name="any" minsize="33"/>
|
||||
<hidden_return voidlock="true"/>
|
||||
</rule>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="x19"/>
|
||||
<register name="x20"/>
|
||||
<register name="x21"/>
|
||||
<register name="x22"/>
|
||||
<register name="x23"/>
|
||||
<register name="x24"/>
|
||||
<register name="x25"/>
|
||||
<register name="x26"/>
|
||||
<register name="x27"/>
|
||||
<register name="x28"/>
|
||||
<register name="x29"/>
|
||||
<register name="x30"/>
|
||||
<register name="sp"/>
|
||||
<!-- vectors -->
|
||||
<register name="d8"/>
|
||||
<register name="d9"/>
|
||||
<register name="d10"/>
|
||||
<register name="d11"/>
|
||||
<register name="d12"/>
|
||||
<register name="d13"/>
|
||||
<register name="d14"/>
|
||||
<register name="d15"/>
|
||||
</unaffected>
|
||||
<killedbycall>
|
||||
<!-- x8: indirect result location register, which is not
|
||||
reflected in the pentry list -->
|
||||
<register name="x8"/>
|
||||
<register name="x9"/>
|
||||
<register name="x10"/>
|
||||
<register name="x11"/>
|
||||
<register name="x12"/>
|
||||
<register name="x13"/>
|
||||
<register name="x14"/>
|
||||
<register name="x15"/>
|
||||
<register name="x16"/>
|
||||
<register name="x17"/>
|
||||
<register name="x18"/>
|
||||
<!-- vectors -->
|
||||
<register name="d16"/>
|
||||
<register name="d17"/>
|
||||
<register name="d18"/>
|
||||
<register name="d19"/>
|
||||
<register name="d20"/>
|
||||
<register name="d21"/>
|
||||
<register name="d22"/>
|
||||
<register name="d23"/>
|
||||
<register name="d24"/>
|
||||
<register name="d25"/>
|
||||
<register name="d26"/>
|
||||
<register name="d27"/>
|
||||
<register name="d28"/>
|
||||
<register name="d29"/>
|
||||
<register name="d30"/>
|
||||
<register name="d31"/>
|
||||
</killedbycall>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
<prototype name="__thiscall" extrapop="0" stackshift="0">
|
||||
<!-- https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64 -->
|
||||
<input>
|
||||
<pentry minsize="8" maxsize="8" storage="hiddenret">
|
||||
<register name="x8"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d0"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d1"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d2"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d3"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d4"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d5"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d6"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d7"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x20"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x1"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x2"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x3"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x4"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x5"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x6"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8" extension="zero">
|
||||
<register name="x7"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="500" align="4">
|
||||
<addr offset="0" space="stack"/>
|
||||
</pentry>
|
||||
<rule>
|
||||
<datatype name="struct" minsize="9"/>
|
||||
<join/>
|
||||
</rule>
|
||||
</input>
|
||||
<output>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d0"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d1"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d2"/>
|
||||
</pentry>
|
||||
<pentry minsize="2" maxsize="8" metatype="float">
|
||||
<register name="d3"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8">
|
||||
<register name="x0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8">
|
||||
<register name="x1"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8">
|
||||
<register name="x2"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="8">
|
||||
<register name="x3"/>
|
||||
</pentry>
|
||||
<rule>
|
||||
<datatype name="homogeneous-float-aggregate"/>
|
||||
<join_per_primitive storage="float"/>
|
||||
</rule>
|
||||
<rule>
|
||||
<datatype name="float"/>
|
||||
<consume storage="float"/>
|
||||
</rule>
|
||||
<rule>
|
||||
<datatype name="any" minsize="1" maxsize="32"/>
|
||||
<join/>
|
||||
</rule>
|
||||
<rule>
|
||||
<datatype name="any" minsize="33"/>
|
||||
<hidden_return voidlock="true"/>
|
||||
</rule>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="x19"/>
|
||||
<register name="x21"/>
|
||||
<register name="x22"/>
|
||||
<register name="x23"/>
|
||||
<register name="x24"/>
|
||||
<register name="x25"/>
|
||||
<register name="x26"/>
|
||||
<register name="x27"/>
|
||||
<register name="x28"/>
|
||||
<register name="x29"/>
|
||||
<register name="x30"/>
|
||||
<register name="sp"/>
|
||||
<!-- vectors -->
|
||||
<register name="d8"/>
|
||||
<register name="d9"/>
|
||||
<register name="d10"/>
|
||||
<register name="d11"/>
|
||||
<register name="d12"/>
|
||||
<register name="d13"/>
|
||||
<register name="d14"/>
|
||||
<register name="d15"/>
|
||||
</unaffected>
|
||||
<killedbycall>
|
||||
<!-- x8: indirect result location register, which is not
|
||||
reflected in the pentry list -->
|
||||
<register name="x8"/>
|
||||
<register name="x9"/>
|
||||
<register name="x10"/>
|
||||
<register name="x11"/>
|
||||
<register name="x12"/>
|
||||
<register name="x13"/>
|
||||
<register name="x14"/>
|
||||
<register name="x15"/>
|
||||
<register name="x16"/>
|
||||
<register name="x17"/>
|
||||
<register name="x18"/>
|
||||
<!-- vectors -->
|
||||
<register name="d16"/>
|
||||
<register name="d17"/>
|
||||
<register name="d18"/>
|
||||
<register name="d19"/>
|
||||
<register name="d20"/>
|
||||
<register name="d21"/>
|
||||
<register name="d22"/>
|
||||
<register name="d23"/>
|
||||
<register name="d24"/>
|
||||
<register name="d25"/>
|
||||
<register name="d26"/>
|
||||
<register name="d27"/>
|
||||
<register name="d28"/>
|
||||
<register name="d29"/>
|
||||
<register name="d30"/>
|
||||
<register name="d31"/>
|
||||
</killedbycall>
|
||||
</prototype>
|
||||
</compiler_spec>
|
|
@ -11,6 +11,7 @@
|
|||
id="AARCH64:LE:64:AppleSilicon">
|
||||
<description>AppleSilicon ARM v8.5-A LE instructions, LE data, AMX extensions</description>
|
||||
<compiler name="default" spec="AARCH64.cspec" id="default"/>
|
||||
<compiler name="Swift" spec="AARCH64_swift.cspec" id="swift"/>
|
||||
<external_name tool="gnu" name="aarch64"/>
|
||||
<external_name tool="gnu" name="aarch64:ilp32"/>
|
||||
<external_name tool="DWARF.register.mapping.file" name="AARCH64.dwarf"/>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue