mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +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 NAME = "Swift Type Metadata Analyzer";
|
||||||
private static final String DESCRIPTION = "Discovers Swift type metadata records.";
|
private static final String DESCRIPTION = "Discovers Swift type metadata records.";
|
||||||
|
|
||||||
|
private SwiftTypeMetadata typeMetadata;
|
||||||
|
|
||||||
public SwiftTypeMetadataAnalyzer() {
|
public SwiftTypeMetadataAnalyzer() {
|
||||||
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
|
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
|
||||||
setDefaultEnablement(true);
|
setDefaultEnablement(true);
|
||||||
|
@ -45,8 +47,11 @@ public class SwiftTypeMetadataAnalyzer extends AbstractAnalyzer {
|
||||||
@Override
|
@Override
|
||||||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
if (typeMetadata != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
SwiftTypeMetadata typeMetadata = new SwiftTypeMetadata(program, monitor, log);
|
typeMetadata = new SwiftTypeMetadata(program, monitor, log);
|
||||||
typeMetadata.markup();
|
typeMetadata.markup();
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
|
@ -54,4 +59,9 @@ public class SwiftTypeMetadataAnalyzer extends AbstractAnalyzer {
|
||||||
}
|
}
|
||||||
return true;
|
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_PROTOCS("__swift5_protos", "swift5_protocols", ".sw5prt"),
|
||||||
BLOCK_ACFUNCS("__swift5_acfuncs", "swift5_accessible_functions", ".sw5acfn"),
|
BLOCK_ACFUNCS("__swift5_acfuncs", "swift5_accessible_functions", ".sw5acfn"),
|
||||||
BLOCK_MPENUM("__swift5_mpenum", "swift5_mpenum", ".sw5mpen"),
|
BLOCK_MPENUM("__swift5_mpenum", "swift5_mpenum", ".sw5mpen"),
|
||||||
BLOCK_TYPES("__swift5_types", "swift5_types", ".sw5tymd"),
|
BLOCK_TYPES("__swift5_types", "swift5_type_metadata", ".sw5tymd"),
|
||||||
BLOCK_ENTRY("__swift5_entry", "swift5_entry", ".sw5entr");
|
BLOCK_ENTRY("__swift5_entry", "swift5_entry", ".sw5entr"),
|
||||||
|
BLOCK_SWIFTAST("__swift_ast", ".swift_ast", "swiftast");
|
||||||
|
|
||||||
private List<String> sectionNames;
|
private List<String> sectionNames;
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
package ghidra.app.util.bin.format.swift;
|
package ghidra.app.util.bin.format.swift;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import ghidra.app.util.bin.*;
|
import ghidra.app.util.bin.*;
|
||||||
import ghidra.app.util.bin.format.swift.types.*;
|
import ghidra.app.util.bin.format.swift.types.*;
|
||||||
|
@ -43,11 +42,11 @@ public class SwiftTypeMetadata {
|
||||||
|
|
||||||
private List<EntryPoint> entryPoints = new ArrayList<>();
|
private List<EntryPoint> entryPoints = new ArrayList<>();
|
||||||
private List<BuiltinTypeDescriptor> builtinTypeDescriptors = 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<AssociatedTypeDescriptor> associatedTypeDescriptors = new ArrayList<>();
|
||||||
private List<CaptureDescriptor> captureDescriptors = new ArrayList<>();
|
private List<CaptureDescriptor> captureDescriptors = new ArrayList<>();
|
||||||
private List<MultiPayloadEnumDescriptor> mpEnumDescriptors = 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<TargetProtocolDescriptor> protocolDescriptors = new ArrayList<>();
|
||||||
private List<TargetProtocolConformanceDescriptor> protocolConformanceDescriptors =
|
private List<TargetProtocolConformanceDescriptor> protocolConformanceDescriptors =
|
||||||
new ArrayList<>();
|
new ArrayList<>();
|
||||||
|
@ -72,6 +71,69 @@ public class SwiftTypeMetadata {
|
||||||
parse();
|
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}
|
* Parses the {@link SwiftTypeMetadata}
|
||||||
*
|
*
|
||||||
|
@ -137,7 +199,7 @@ public class SwiftTypeMetadata {
|
||||||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||||
Address blockStart = block.getStart();
|
Address blockStart = block.getStart();
|
||||||
reader.setPointerIndex(blockStart.getOffset());
|
reader.setPointerIndex(blockStart.getOffset());
|
||||||
int i = 0;
|
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||||
while (i + BuiltinTypeDescriptor.SIZE <= block.getSize()) {
|
while (i + BuiltinTypeDescriptor.SIZE <= block.getSize()) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
BuiltinTypeDescriptor descriptor = new BuiltinTypeDescriptor(reader);
|
BuiltinTypeDescriptor descriptor = new BuiltinTypeDescriptor(reader);
|
||||||
|
@ -145,6 +207,7 @@ public class SwiftTypeMetadata {
|
||||||
markupList.add(new SwiftStructureInfo(descriptor,
|
markupList.add(new SwiftStructureInfo(descriptor,
|
||||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||||
i += BuiltinTypeDescriptor.SIZE;
|
i += BuiltinTypeDescriptor.SIZE;
|
||||||
|
i = skipZeroEntries(reader, i, block.getSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,11 +231,11 @@ public class SwiftTypeMetadata {
|
||||||
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||||
Address blockStart = block.getStart();
|
Address blockStart = block.getStart();
|
||||||
reader.setPointerIndex(blockStart.getOffset());
|
reader.setPointerIndex(blockStart.getOffset());
|
||||||
int i = 0;
|
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||||
while (i + FieldDescriptor.SIZE <= block.getSize()) {
|
while (i + FieldDescriptor.SIZE <= block.getSize()) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
FieldDescriptor descriptor = new FieldDescriptor(reader);
|
FieldDescriptor descriptor = new FieldDescriptor(reader);
|
||||||
fieldDescriptors.add(descriptor);
|
fieldDescriptors.put(descriptor.getBase(), descriptor);
|
||||||
markupList.add(new SwiftStructureInfo(descriptor,
|
markupList.add(new SwiftStructureInfo(descriptor,
|
||||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||||
List<FieldRecord> records = descriptor.getFieldRecords();
|
List<FieldRecord> records = descriptor.getFieldRecords();
|
||||||
|
@ -184,6 +247,7 @@ public class SwiftTypeMetadata {
|
||||||
null)));
|
null)));
|
||||||
}
|
}
|
||||||
i += descriptor.getNumFields() * FieldRecord.SIZE;
|
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)) {
|
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||||
Address blockStart = block.getStart();
|
Address blockStart = block.getStart();
|
||||||
reader.setPointerIndex(blockStart.getOffset());
|
reader.setPointerIndex(blockStart.getOffset());
|
||||||
int i = 0;
|
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||||
while (i + AssociatedTypeDescriptor.SIZE <= block.getSize()) {
|
while (i + AssociatedTypeDescriptor.SIZE <= block.getSize()) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
AssociatedTypeDescriptor descriptor = new AssociatedTypeDescriptor(reader);
|
AssociatedTypeDescriptor descriptor = new AssociatedTypeDescriptor(reader);
|
||||||
|
@ -223,6 +287,7 @@ public class SwiftTypeMetadata {
|
||||||
blockStart.add(i + j * AssociatedTypeRecord.SIZE), null)));
|
blockStart.add(i + j * AssociatedTypeRecord.SIZE), null)));
|
||||||
}
|
}
|
||||||
i += descriptor.getNumAssociatedTypes() * AssociatedTypeRecord.SIZE;
|
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)) {
|
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||||
Address blockStart = block.getStart();
|
Address blockStart = block.getStart();
|
||||||
reader.setPointerIndex(blockStart.getOffset());
|
reader.setPointerIndex(blockStart.getOffset());
|
||||||
int i = 0;
|
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||||
while (i + CaptureDescriptor.SIZE <= block.getSize()) {
|
while (i + CaptureDescriptor.SIZE <= block.getSize()) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
CaptureDescriptor descriptor = new CaptureDescriptor(reader);
|
CaptureDescriptor descriptor = new CaptureDescriptor(reader);
|
||||||
|
@ -271,6 +336,7 @@ public class SwiftTypeMetadata {
|
||||||
blockStart.add(i + j * MetadataSourceRecord.SIZE), null)));
|
blockStart.add(i + j * MetadataSourceRecord.SIZE), null)));
|
||||||
}
|
}
|
||||||
i += descriptor.getNumMetadataSources() * MetadataSourceRecord.SIZE;
|
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)) {
|
for (MemoryBlock block : SwiftUtils.getSwiftBlocks(section, program)) {
|
||||||
Address blockStart = block.getStart();
|
Address blockStart = block.getStart();
|
||||||
reader.setPointerIndex(blockStart.getOffset());
|
reader.setPointerIndex(blockStart.getOffset());
|
||||||
int i = 0;
|
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||||
while (i < block.getSize()) {
|
while (i < block.getSize()) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
MultiPayloadEnumDescriptor descriptor = new MultiPayloadEnumDescriptor(reader);
|
MultiPayloadEnumDescriptor descriptor = new MultiPayloadEnumDescriptor(reader);
|
||||||
|
@ -302,6 +368,7 @@ public class SwiftTypeMetadata {
|
||||||
markupList.add(new SwiftStructureInfo(descriptor,
|
markupList.add(new SwiftStructureInfo(descriptor,
|
||||||
new SwiftStructureAddress(blockStart.add(i), null)));
|
new SwiftStructureAddress(blockStart.add(i), null)));
|
||||||
i += MultiPayloadEnumDescriptor.SIZE + descriptor.getContentsSize();
|
i += MultiPayloadEnumDescriptor.SIZE + descriptor.getContentsSize();
|
||||||
|
i = skipZeroEntries(reader, i, block.getSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,7 +464,7 @@ public class SwiftTypeMetadata {
|
||||||
yield null;
|
yield null;
|
||||||
};
|
};
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
typeDescriptors.add(descriptor);
|
typeDescriptors.put(descriptor.getName(), descriptor);
|
||||||
markupList.add(new SwiftStructureInfo(descriptor,
|
markupList.add(new SwiftStructureInfo(descriptor,
|
||||||
new SwiftStructureAddress(addrPair.structAddr(), addrPair.pointerAddr())));
|
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 section The {@link SwiftSection} that contains the pointer table
|
||||||
* @param reader A {@link BinaryReader}
|
* @param reader A {@link BinaryReader}
|
||||||
|
@ -428,11 +495,10 @@ public class SwiftTypeMetadata {
|
||||||
reader.setPointerIndex(blockAddr.getOffset() + i);
|
reader.setPointerIndex(blockAddr.getOffset() + i);
|
||||||
Address pointerAddr = blockAddr.add(i);
|
Address pointerAddr = blockAddr.add(i);
|
||||||
int offset = reader.readInt(pointerAddr.getOffset());
|
int offset = reader.readInt(pointerAddr.getOffset());
|
||||||
if (offset == 0) {
|
if (offset != 0) {
|
||||||
break;
|
Address structAddr = pointerAddr.add(offset);
|
||||||
|
result.add(new SwiftStructureAddress(structAddr, pointerAddr));
|
||||||
}
|
}
|
||||||
Address structAddr = pointerAddr.add(offset);
|
|
||||||
result.add(new SwiftStructureAddress(structAddr, pointerAddr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,7 +520,7 @@ public class SwiftTypeMetadata {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
try {
|
try {
|
||||||
SwiftStructure struct = structInfo.struct();
|
SwiftTypeMetadataStructure struct = structInfo.struct();
|
||||||
DataType dt = struct.toDataType();
|
DataType dt = struct.toDataType();
|
||||||
DataUtilities.createData(program, structInfo.addr().structAddr(), dt, -1,
|
DataUtilities.createData(program, structInfo.addr().structAddr(), dt, -1,
|
||||||
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
||||||
|
@ -465,12 +531,37 @@ public class SwiftTypeMetadata {
|
||||||
relativePtrDataType, -1, ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
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);
|
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
|
* 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
|
* The {@link Address} of a {@link SwiftTypeMetadataStructure} and the optional {@link Address}
|
||||||
* pointer
|
* of its pointer
|
||||||
*
|
*
|
||||||
* @param structAddr The {@link Address} of a {@link SwiftStructure}
|
* @param structAddr The {@link Address} of a {@link SwiftTypeMetadataStructure}
|
||||||
* @param pointerAddr The {@link Address} of a pointer to a {@link SwiftStructure} (could be
|
* @param pointerAddr The {@link Address} of a pointer to a {@link SwiftTypeMetadataStructure}
|
||||||
* null if there is no associated pointer}
|
* (could be null if there is no associated pointer}
|
||||||
*/
|
*/
|
||||||
private record SwiftStructureAddress(Address structAddr, Address pointerAddr) {}
|
private record SwiftStructureAddress(Address structAddr, Address pointerAddr) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about a {@link SwiftStructure}
|
* Information about a {@link SwiftTypeMetadataStructure}
|
||||||
*
|
*
|
||||||
* @param struct The {@link SwiftStructure}
|
* @param struct The {@link SwiftTypeMetadataStructure}
|
||||||
* @param addr The {@link SwiftStructureAddress address} of the {@link SwiftStructure}
|
* @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
|
@Override
|
||||||
public String toString() {
|
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;
|
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}
|
* 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 java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.app.util.bin.format.swift.SwiftUtils;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public AssociatedTypeDescriptor(BinaryReader reader) throws IOException {
|
public AssociatedTypeDescriptor(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
conformingTypeName = reader.readNext(SwiftUtils::relativeString);
|
conformingTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||||
protocolTypeName = reader.readNext(SwiftUtils::relativeString);
|
protocolTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||||
numAssociatedTypes = reader.readNextInt();
|
numAssociatedTypes = reader.readNextInt();
|
||||||
|
|
|
@ -18,7 +18,7 @@ package ghidra.app.util.bin.format.swift.types;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.app.util.bin.format.swift.SwiftUtils;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public AssociatedTypeRecord(BinaryReader reader) throws IOException {
|
public AssociatedTypeRecord(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
name = reader.readNext(SwiftUtils::relativeString);
|
name = reader.readNext(SwiftUtils::relativeString);
|
||||||
substitutedTypeName = 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 java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public BuiltinTypeDescriptor(BinaryReader reader) throws IOException {
|
public BuiltinTypeDescriptor(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
typeName = reader.readNext(SwiftUtils::relativeString);
|
typeName = reader.readNext(SwiftUtils::relativeString);
|
||||||
size = reader.readNextInt();
|
size = reader.readNextInt();
|
||||||
alignmentAndFlags = reader.readNextInt();
|
alignmentAndFlags = reader.readNextInt();
|
||||||
|
|
|
@ -20,10 +20,8 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.format.swift.SwiftStructure;
|
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||||
import ghidra.program.model.data.CategoryPath;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.DataType;
|
|
||||||
import ghidra.program.model.data.StructureDataType;
|
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public CaptureDescriptor(BinaryReader reader) throws IOException {
|
public CaptureDescriptor(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
numCaptureTypes = reader.readNextInt();
|
numCaptureTypes = reader.readNextInt();
|
||||||
numMetadataSources = reader.readNextInt();
|
numMetadataSources = reader.readNextInt();
|
||||||
numBindings = reader.readNextInt();
|
numBindings = reader.readNextInt();
|
||||||
|
|
|
@ -18,7 +18,8 @@ package ghidra.app.util.bin.format.swift.types;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public CaptureTypeRecord(BinaryReader reader) throws IOException {
|
public CaptureTypeRecord(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ package ghidra.app.util.bin.format.swift.types;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.app.util.bin.format.swift.SwiftUtils;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
@ -26,7 +26,7 @@ import ghidra.util.exception.DuplicateNameException;
|
||||||
/**
|
/**
|
||||||
* Represents a Swift entry point
|
* 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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public EntryPoint(BinaryReader reader) throws IOException {
|
public EntryPoint(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
entryPoint = reader.readNextInt();
|
entryPoint = reader.readNextInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public FieldDescriptor(BinaryReader reader) throws IOException {
|
public FieldDescriptor(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||||
superclass = reader.readNextInt();
|
superclass = reader.readNextInt();
|
||||||
kind = reader.readNextUnsignedShort();
|
kind = reader.readNextUnsignedShort();
|
||||||
|
|
|
@ -18,7 +18,8 @@ package ghidra.app.util.bin.format.swift.types;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public FieldRecord(BinaryReader reader) throws IOException {
|
public FieldRecord(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
flags = reader.readNextInt();
|
flags = reader.readNextInt();
|
||||||
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||||
fieldName = 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 java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public MetadataSourceRecord(BinaryReader reader) throws IOException {
|
public MetadataSourceRecord(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
mangledTypeName = reader.readNext(SwiftUtils::relativeString);
|
||||||
mangledMetadataSource = 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 java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.app.util.bin.format.swift.SwiftUtils;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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
|
* 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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public MultiPayloadEnumDescriptor(BinaryReader reader) throws IOException {
|
public MultiPayloadEnumDescriptor(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
typeName = reader.readNext(SwiftUtils::relativeString);
|
typeName = reader.readNext(SwiftUtils::relativeString);
|
||||||
int size = (reader.readNextInt() >> 16) & 0xffff;
|
int size = (reader.readNextInt() >> 16) & 0xffff;
|
||||||
reader.setPointerIndex(reader.getPointerIndex() - 4);
|
reader.setPointerIndex(reader.getPointerIndex() - 4);
|
||||||
|
|
|
@ -19,9 +19,7 @@ import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||||
import ghidra.program.model.data.CategoryPath;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.DataType;
|
|
||||||
import ghidra.program.model.data.StructureDataType;
|
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,7 +18,8 @@ package ghidra.app.util.bin.format.swift.types;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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 flags;
|
||||||
private int parent;
|
private int parent;
|
||||||
|
@ -39,6 +45,7 @@ public class TargetContextDescriptor implements SwiftStructure {
|
||||||
* @throws IOException if there was an IO-related problem creating the structure
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public TargetContextDescriptor(BinaryReader reader) throws IOException {
|
public TargetContextDescriptor(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
flags = reader.readNextInt();
|
flags = reader.readNextInt();
|
||||||
parent = reader.readNextInt();
|
parent = reader.readNextInt();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@ package ghidra.app.util.bin.format.swift.types;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
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.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
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>
|
* @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 protocolDescriptor;
|
||||||
private int nominalTypeDescriptor;
|
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
|
* @throws IOException if there was an IO-related problem creating the structure
|
||||||
*/
|
*/
|
||||||
public TargetProtocolConformanceDescriptor(BinaryReader reader) throws IOException {
|
public TargetProtocolConformanceDescriptor(BinaryReader reader) throws IOException {
|
||||||
|
super(reader.getPointerIndex());
|
||||||
protocolDescriptor = reader.readNextInt();
|
protocolDescriptor = reader.readNextInt();
|
||||||
nominalTypeDescriptor = reader.readNextInt();
|
nominalTypeDescriptor = reader.readNextInt();
|
||||||
protocolWitnessTable = reader.readNextInt();
|
protocolWitnessTable = reader.readNextInt();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package ghidra.app.util.bin.format.swift.types;
|
package ghidra.app.util.bin.format.swift.types;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
import ghidra.app.util.bin.format.swift.SwiftUtils;
|
||||||
|
@ -73,6 +74,20 @@ public class TargetTypeContextDescriptor extends TargetContextDescriptor {
|
||||||
return fields;
|
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
|
@Override
|
||||||
public String getStructureName() {
|
public String getStructureName() {
|
||||||
return getMyStructureName();
|
return getMyStructureName();
|
||||||
|
|
|
@ -73,6 +73,7 @@ public class DemangledDataType extends DemangledType {
|
||||||
public final static String LONG = "long";
|
public final static String LONG = "long";
|
||||||
public final static String LONG_LONG = "long long";
|
public final static String LONG_LONG = "long long";
|
||||||
public final static String FLOAT = "float";
|
public final static String FLOAT = "float";
|
||||||
|
public final static String FLOAT2 = "float2";
|
||||||
public final static String DOUBLE = "double";
|
public final static String DOUBLE = "double";
|
||||||
public final static String INT8 = "__int8";
|
public final static String INT8 = "__int8";
|
||||||
public final static String INT16 = "__int16";
|
public final static String INT16 = "__int16";
|
||||||
|
@ -94,7 +95,7 @@ public class DemangledDataType extends DemangledType {
|
||||||
|
|
||||||
public final static String[] PRIMITIVES =
|
public final static String[] PRIMITIVES =
|
||||||
{ VOID, BOOL, CHAR, WCHAR_T, WCHAR16, WCHAR32, SHORT, INT, INT0_T, LONG,
|
{ 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 int arrayDimensions = 0;
|
||||||
private boolean isClass;
|
private boolean isClass;
|
||||||
|
@ -293,6 +294,9 @@ public class DemangledDataType extends DemangledType {
|
||||||
else if (FLOAT.equals(name)) {
|
else if (FLOAT.equals(name)) {
|
||||||
dt = FloatDataType.dataType;
|
dt = FloatDataType.dataType;
|
||||||
}
|
}
|
||||||
|
else if (FLOAT2.equals(name)) {
|
||||||
|
dt = Float2DataType.dataType;
|
||||||
|
}
|
||||||
else if (FLOAT128.equals(name)) {
|
else if (FLOAT128.equals(name)) {
|
||||||
dt = new TypedefDataType(FLOAT128, Float16DataType.dataType);
|
dt = new TypedefDataType(FLOAT128, Float16DataType.dataType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class DemangledFunction extends DemangledObject {
|
||||||
protected DemangledDataType returnType;
|
protected DemangledDataType returnType;
|
||||||
protected String callingConvention;// __cdecl, __thiscall, etc.
|
protected String callingConvention;// __cdecl, __thiscall, etc.
|
||||||
protected boolean thisPassedOnStack = true;
|
protected boolean thisPassedOnStack = true;
|
||||||
protected List<DemangledDataType> parameters = new ArrayList<>();
|
protected List<DemangledParameter> parameters = new ArrayList<>();
|
||||||
protected DemangledTemplate template;
|
protected DemangledTemplate template;
|
||||||
protected boolean isOverloadedOperator = false;
|
protected boolean isOverloadedOperator = false;
|
||||||
protected SourceType signatureSourceType = SourceType.ANALYSIS;
|
protected SourceType signatureSourceType = SourceType.ANALYSIS;
|
||||||
|
@ -140,11 +140,15 @@ public class DemangledFunction extends DemangledObject {
|
||||||
this.isOverloadedOperator = isOverloadedOperator;
|
this.isOverloadedOperator = isOverloadedOperator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addParameter(DemangledDataType parameter) {
|
public void addParameter(DemangledParameter parameter) {
|
||||||
parameters.add(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);
|
return new ArrayList<>(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +327,7 @@ public class DemangledFunction extends DemangledObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addParameters(StringBuilder buffer, boolean format) {
|
protected void addParameters(StringBuilder buffer, boolean format) {
|
||||||
Iterator<DemangledDataType> paramIterator = parameters.iterator();
|
Iterator<DemangledParameter> paramIterator = parameters.iterator();
|
||||||
buffer.append('(');
|
buffer.append('(');
|
||||||
int padLength = format ? buffer.length() : 0;
|
int padLength = format ? buffer.length() : 0;
|
||||||
String pad = StringUtils.rightPad("", padLength);
|
String pad = StringUtils.rightPad("", padLength);
|
||||||
|
@ -332,7 +336,11 @@ public class DemangledFunction extends DemangledObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (paramIterator.hasNext()) {
|
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()) {
|
if (paramIterator.hasNext()) {
|
||||||
buffer.append(',');
|
buffer.append(',');
|
||||||
if (format) {
|
if (format) {
|
||||||
|
@ -353,9 +361,9 @@ public class DemangledFunction extends DemangledObject {
|
||||||
public String getParameterString() {
|
public String getParameterString() {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
buffer.append('(');
|
buffer.append('(');
|
||||||
Iterator<DemangledDataType> dditer = parameters.iterator();
|
Iterator<DemangledParameter> dditer = parameters.iterator();
|
||||||
while (dditer.hasNext()) {
|
while (dditer.hasNext()) {
|
||||||
buffer.append(dditer.next().getSignature());
|
buffer.append(dditer.next().getType().getSignature());
|
||||||
if (dditer.hasNext()) {
|
if (dditer.hasNext()) {
|
||||||
buffer.append(',');
|
buffer.append(',');
|
||||||
}
|
}
|
||||||
|
@ -576,13 +584,13 @@ public class DemangledFunction extends DemangledObject {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DemangledDataType lastType = parameters.get(parameters.size() - 1);
|
DemangledDataType lastType = parameters.get(parameters.size() - 1).getType();
|
||||||
return lastType.isVarArgs();
|
return lastType.isVarArgs();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasVoidParams() {
|
private boolean hasVoidParams() {
|
||||||
if (parameters.size() == 1) {
|
if (parameters.size() == 1) {
|
||||||
DemangledDataType ddt = parameters.get(0);
|
DemangledDataType ddt = parameters.get(0).getType();
|
||||||
return ddt.isVoid() && !ddt.isPointer();
|
return ddt.isVoid() && !ddt.isPointer();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -634,7 +642,7 @@ public class DemangledFunction extends DemangledObject {
|
||||||
// If returnType is null check for constructor or destructor names
|
// If returnType is null check for constructor or destructor names
|
||||||
if (THIS_CALL.equals(function.getCallingConventionName())) {
|
if (THIS_CALL.equals(function.getCallingConventionName())) {
|
||||||
String n = getName();
|
String n = getName();
|
||||||
if (n.equals(namespace.getName())) {
|
if (namespace != null && n.equals(namespace.getName())) {
|
||||||
// constructor
|
// constructor
|
||||||
return DataType.DEFAULT;
|
return DataType.DEFAULT;
|
||||||
}
|
}
|
||||||
|
@ -698,17 +706,18 @@ public class DemangledFunction extends DemangledObject {
|
||||||
private List<ParameterDefinitionImpl> convertMangledToParamDef(Program program) {
|
private List<ParameterDefinitionImpl> convertMangledToParamDef(Program program) {
|
||||||
|
|
||||||
List<ParameterDefinitionImpl> args = new ArrayList<>();
|
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.
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
if (param.isVarArgs()) {
|
if (type.isVarArgs()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataType dt = param.getDataType(program.getDataTypeManager());
|
DataType dt = type.getDataType(program.getDataTypeManager());
|
||||||
args.add(new ParameterDefinitionImpl(null, dt, null));
|
args.add(new ParameterDefinitionImpl(param.getLabel(), dt, null));
|
||||||
}
|
}
|
||||||
return args;
|
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.ByteProvider;
|
||||||
import ghidra.app.util.bin.ByteProviderWrapper;
|
import ghidra.app.util.bin.ByteProviderWrapper;
|
||||||
import ghidra.app.util.bin.format.macho.*;
|
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.bin.format.ubi.*;
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.formats.gfilesystem.*;
|
import ghidra.formats.gfilesystem.*;
|
||||||
|
@ -60,7 +61,13 @@ public class MachoLoader extends AbstractLibrarySupportLoader {
|
||||||
MachHeader machHeader = new MachHeader(provider);
|
MachHeader machHeader = new MachHeader(provider);
|
||||||
String magic =
|
String magic =
|
||||||
CpuTypes.getMagicString(machHeader.getCpuType(), machHeader.getCpuSubType());
|
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) {
|
for (QueryResult result : results) {
|
||||||
loadSpecs.add(new LoadSpec(this, machHeader.getImageBase(), result));
|
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.PortableExecutable.SectionLayout;
|
||||||
import ghidra.app.util.bin.format.pe.debug.DebugCOFFSymbol;
|
import ghidra.app.util.bin.format.pe.debug.DebugCOFFSymbol;
|
||||||
import ghidra.app.util.bin.format.pe.debug.DebugDirectoryParser;
|
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.app.util.importer.MessageLog;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
|
@ -904,6 +905,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
||||||
CLI("cli", "cli"),
|
CLI("cli", "cli"),
|
||||||
Rustc(RustConstants.RUST_COMPILER, RustConstants.RUST_COMPILER),
|
Rustc(RustConstants.RUST_COMPILER, RustConstants.RUST_COMPILER),
|
||||||
GOLANG("golang", "golang"),
|
GOLANG("golang", "golang"),
|
||||||
|
Swift("swift", "swift"),
|
||||||
Unknown("unknown", "unknown"),
|
Unknown("unknown", "unknown"),
|
||||||
|
|
||||||
// The following values represent the presence of ambiguous indicators
|
// The following values represent the presence of ambiguous indicators
|
||||||
|
@ -969,6 +971,15 @@ public class PeLoader extends AbstractPeDebugLoader {
|
||||||
}
|
}
|
||||||
return CompilerEnum.Rustc;
|
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)
|
// Check for managed code (.NET)
|
||||||
if (pe.getNTHeader().getOptionalHeader().isCLI()) {
|
if (pe.getNTHeader().getOptionalHeader().isCLI()) {
|
||||||
|
|
|
@ -485,7 +485,7 @@ public class GnuDemanglerParser {
|
||||||
//
|
//
|
||||||
setNameAndNamespace(function, simpleName);
|
setNameAndNamespace(function, simpleName);
|
||||||
|
|
||||||
for (DemangledDataType parameter : signatureParts.getParameters()) {
|
for (DemangledParameter parameter : signatureParts.getParameters()) {
|
||||||
function.addParameter(parameter);
|
function.addParameter(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,9 +630,9 @@ public class GnuDemanglerParser {
|
||||||
* Reason being, you need to take into account nested templates
|
* Reason being, you need to take into account nested templates
|
||||||
* and function pointers.
|
* and function pointers.
|
||||||
*/
|
*/
|
||||||
private List<DemangledDataType> parseParameters(String parameterString) {
|
private List<DemangledParameter> parseParameters(String parameterString) {
|
||||||
List<String> parameterStrings = tokenizeParameters(parameterString);
|
List<String> parameterStrings = tokenizeParameters(parameterString);
|
||||||
List<DemangledDataType> parameters = convertIntoParameters(parameterStrings);
|
List<DemangledParameter> parameters = convertIntoParameters(parameterStrings);
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,12 +735,12 @@ public class GnuDemanglerParser {
|
||||||
* This method converts each parameter string into
|
* This method converts each parameter string into
|
||||||
* actual DemangledDataType objects.
|
* actual DemangledDataType objects.
|
||||||
*/
|
*/
|
||||||
private List<DemangledDataType> convertIntoParameters(List<String> parameterStrings) {
|
private List<DemangledParameter> convertIntoParameters(List<String> parameterStrings) {
|
||||||
List<DemangledDataType> parameters = new ArrayList<>();
|
List<DemangledParameter> parameters = new ArrayList<>();
|
||||||
|
|
||||||
for (String parameter : parameterStrings) {
|
for (String parameter : parameterStrings) {
|
||||||
DemangledDataType dt = parseParameter(parameter);
|
DemangledDataType dt = parseParameter(parameter);
|
||||||
parameters.add(dt);
|
parameters.add(new DemangledParameter(dt));
|
||||||
}
|
}
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
|
@ -1311,10 +1311,10 @@ public class GnuDemanglerParser {
|
||||||
contents = string.substring(1, string.length() - 1);
|
contents = string.substring(1, string.length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DemangledDataType> parameters = parseParameters(contents);
|
List<DemangledParameter> parameters = parseParameters(contents);
|
||||||
DemangledTemplate template = new DemangledTemplate();
|
DemangledTemplate template = new DemangledTemplate();
|
||||||
for (DemangledDataType parameter : parameters) {
|
for (DemangledParameter parameter : parameters) {
|
||||||
template.addParameter(parameter);
|
template.addParameter(parameter.getType());
|
||||||
}
|
}
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
@ -1399,16 +1399,16 @@ public class GnuDemanglerParser {
|
||||||
return dfp;
|
return dfp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DemangledFunctionPointer createFunctionPointer(String paramerterString,
|
private DemangledFunctionPointer createFunctionPointer(String parameterString,
|
||||||
String returnType) {
|
String returnType) {
|
||||||
|
|
||||||
List<DemangledDataType> parameters = parseParameters(paramerterString);
|
List<DemangledParameter> parameters = parseParameters(parameterString);
|
||||||
|
|
||||||
DemangledFunctionPointer dfp = new DemangledFunctionPointer(mangledSource, demangledSource);
|
DemangledFunctionPointer dfp = new DemangledFunctionPointer(mangledSource, demangledSource);
|
||||||
DemangledDataType returnDataType = parseReturnType(returnType);
|
DemangledDataType returnDataType = parseReturnType(returnType);
|
||||||
dfp.setReturnType(returnDataType);
|
dfp.setReturnType(returnDataType);
|
||||||
for (DemangledDataType parameter : parameters) {
|
for (DemangledParameter parameter : parameters) {
|
||||||
dfp.addParameter(parameter);
|
dfp.addParameter(parameter.getType());
|
||||||
}
|
}
|
||||||
return dfp;
|
return dfp;
|
||||||
}
|
}
|
||||||
|
@ -1889,8 +1889,8 @@ public class GnuDemanglerParser {
|
||||||
// operator itself could be in a class namespace
|
// operator itself could be in a class namespace
|
||||||
setNameAndNamespace(function, operatorText);
|
setNameAndNamespace(function, operatorText);
|
||||||
|
|
||||||
List<DemangledDataType> parameters = parseParameters(parametersText);
|
List<DemangledParameter> parameters = parseParameters(parametersText);
|
||||||
for (DemangledDataType parameter : parameters) {
|
for (DemangledParameter parameter : parameters) {
|
||||||
function.addParameter(parameter);
|
function.addParameter(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2029,7 +2029,7 @@ public class GnuDemanglerParser {
|
||||||
private String name;
|
private String name;
|
||||||
private String rawParameterPrefix;
|
private String rawParameterPrefix;
|
||||||
|
|
||||||
private List<DemangledDataType> parameters;
|
private List<DemangledParameter> parameters;
|
||||||
|
|
||||||
FunctionSignatureParts(String signatureString) {
|
FunctionSignatureParts(String signatureString) {
|
||||||
|
|
||||||
|
@ -2077,7 +2077,7 @@ public class GnuDemanglerParser {
|
||||||
return isFunction;
|
return isFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DemangledDataType> getParameters() {
|
List<DemangledParameter> getParameters() {
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,9 +54,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertName(object, "bob");
|
assertName(object, "bob");
|
||||||
|
|
||||||
DemangledFunction function = (DemangledFunction) object;
|
DemangledFunction function = (DemangledFunction) object;
|
||||||
List<DemangledDataType> parameters = function.getParameters();
|
List<DemangledParameter> parameters = function.getParameters();
|
||||||
assertEquals(1, parameters.size());
|
assertEquals(1, parameters.size());
|
||||||
DemangledDataType p1 = parameters.get(0);
|
DemangledDataType p1 = parameters.get(0).getType();
|
||||||
assertEquals("bob(int const[8] (*) [12])", p1.getOriginalDemangled());
|
assertEquals("bob(int const[8] (*) [12])", p1.getOriginalDemangled());
|
||||||
assertEquals("undefined bob(int const *[])", object.getSignature(false));
|
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*)");
|
DemangledObject object = parser.parse("fake", "Layout::graphNew(short[][][][], char*)");
|
||||||
assertType(object, DemangledFunction.class);
|
assertType(object, DemangledFunction.class);
|
||||||
DemangledFunction function = (DemangledFunction) object;
|
DemangledFunction function = (DemangledFunction) object;
|
||||||
List<DemangledDataType> parameters = function.getParameters();
|
List<DemangledParameter> parameters = function.getParameters();
|
||||||
assertEquals(2, parameters.size());
|
assertEquals(2, parameters.size());
|
||||||
DemangledDataType p1 = parameters.get(0);
|
DemangledDataType p1 = parameters.get(0).getType();
|
||||||
assertEquals(4, p1.getArrayDimensions());
|
assertEquals(4, p1.getArrayDimensions());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,12 +153,12 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
DemangledFunction method = (DemangledFunction) object;
|
DemangledFunction method = (DemangledFunction) object;
|
||||||
|
|
||||||
List<DemangledDataType> parameters = method.getParameters();
|
List<DemangledParameter> parameters = method.getParameters();
|
||||||
assertEquals(4, parameters.size());
|
assertEquals(4, parameters.size());
|
||||||
assertEquals("unsigned long (*)(long const &)", parameters.get(0).getSignature());
|
assertEquals("unsigned long (*)(long const &)", parameters.get(0).getType().getSignature());
|
||||||
assertEquals("unsigned long", parameters.get(1).getSignature());
|
assertEquals("unsigned long", parameters.get(1).getType().getSignature());
|
||||||
assertEquals("unsigned long", parameters.get(2).getSignature());
|
assertEquals("unsigned long", parameters.get(2).getType().getSignature());
|
||||||
assertEquals("float", parameters.get(3).getSignature());
|
assertEquals("float", parameters.get(3).getType().getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -176,9 +176,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
"_Rb_tree<Location,Location,std::_Identity<Location>,std::less<Location>,std::allocator<Location>>");
|
"_Rb_tree<Location,Location,std::_Identity<Location>,std::less<Location>,std::allocator<Location>>");
|
||||||
|
|
||||||
DemangledFunction function = (DemangledFunction) object;
|
DemangledFunction function = (DemangledFunction) object;
|
||||||
List<DemangledDataType> parameters = function.getParameters();
|
List<DemangledParameter> parameters = function.getParameters();
|
||||||
assertEquals(1, parameters.size());
|
assertEquals(1, parameters.size());
|
||||||
assertEquals("Location const &", parameters.get(0).getSignature());
|
assertEquals("Location const &", parameters.get(0).getType().getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -194,7 +194,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertType(object, DemangledFunction.class);
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
DemangledFunction function = (DemangledFunction) object;
|
DemangledFunction function = (DemangledFunction) object;
|
||||||
List<DemangledDataType> parameters = function.getParameters();
|
List<DemangledParameter> parameters = function.getParameters();
|
||||||
|
|
||||||
assertEquals(
|
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&)>",
|
"__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 &)",
|
"bool (*)(std::pair<unsigned long,PcodeOp *> const &,std::pair<unsigned long,PcodeOp *> const &)",
|
||||||
parameters.get(2).toString());
|
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());
|
assertEquals("bool", fptr.getReturnType().getName());
|
||||||
|
|
||||||
|
@ -234,9 +234,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"undefined std::set<bbnode*,std::less<bbnode*>,std::allocator<bbnode*>>::insert(bbnode const * &)",
|
"undefined std::set<bbnode*,std::less<bbnode*>,std::allocator<bbnode*>>::insert(bbnode const * &)",
|
||||||
method.getSignature(false));
|
method.getSignature(false));
|
||||||
List<DemangledDataType> parameters = method.getParameters();
|
List<DemangledParameter> parameters = method.getParameters();
|
||||||
assertEquals(1, parameters.size());
|
assertEquals(1, parameters.size());
|
||||||
assertEquals("bbnode const * &", parameters.get(0).getSignature());
|
assertEquals("bbnode const * &", parameters.get(0).getType().getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -252,9 +252,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
DemangledFunction method = (DemangledFunction) object;
|
DemangledFunction method = (DemangledFunction) object;
|
||||||
assertEquals("undefined Bar::Fred::Fred(int)", method.getSignature(false));
|
assertEquals("undefined Bar::Fred::Fred(int)", method.getSignature(false));
|
||||||
|
|
||||||
List<DemangledDataType> parameters = method.getParameters();
|
List<DemangledParameter> parameters = method.getParameters();
|
||||||
assertEquals(1, parameters.size());
|
assertEquals(1, parameters.size());
|
||||||
assertEquals("int", parameters.get(0).getSignature());
|
assertEquals("int", parameters.get(0).getType().getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -428,9 +428,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
DemangledFunction function = (DemangledFunction) object;
|
DemangledFunction function = (DemangledFunction) object;
|
||||||
assertEquals("undefined Foo::getBool(float)", function.getSignature(false));
|
assertEquals("undefined Foo::getBool(float)", function.getSignature(false));
|
||||||
|
|
||||||
List<DemangledDataType> parameters = function.getParameters();
|
List<DemangledParameter> parameters = function.getParameters();
|
||||||
assertEquals(1, parameters.size());
|
assertEquals(1, parameters.size());
|
||||||
assertEquals("float", parameters.get(0).getSignature());
|
assertEquals("float", parameters.get(0).getType().getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -447,13 +447,13 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
DemangledFunction function = (DemangledFunction) object;
|
DemangledFunction function = (DemangledFunction) object;
|
||||||
|
|
||||||
List<DemangledDataType> parameters = function.getParameters();
|
List<DemangledParameter> parameters = function.getParameters();
|
||||||
assertEquals(5, parameters.size());
|
assertEquals(5, parameters.size());
|
||||||
assertEquals("int", parameters.get(0).getSignature());
|
assertEquals("int", parameters.get(0).getType().getSignature());
|
||||||
assertEquals("double", parameters.get(1).getSignature());
|
assertEquals("double", parameters.get(1).getType().getSignature());
|
||||||
assertEquals("char", parameters.get(2).getSignature());
|
assertEquals("char", parameters.get(2).getType().getSignature());
|
||||||
assertEquals("long", parameters.get(3).getSignature());
|
assertEquals("long", parameters.get(3).getType().getSignature());
|
||||||
assertEquals("short", parameters.get(4).getSignature());
|
assertEquals("short", parameters.get(4).getType().getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -827,13 +827,13 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
DemangledFunction method = (DemangledFunction) object;
|
DemangledFunction method = (DemangledFunction) object;
|
||||||
|
|
||||||
List<DemangledDataType> parameters = method.getParameters();
|
List<DemangledParameter> parameters = method.getParameters();
|
||||||
assertEquals(5, parameters.size());
|
assertEquals(5, parameters.size());
|
||||||
assertEquals("SECTION_INFO *", parameters.get(0).getSignature());
|
assertEquals("SECTION_INFO *", parameters.get(0).getType().getSignature());
|
||||||
assertEquals("int *", parameters.get(1).getSignature());
|
assertEquals("int *", parameters.get(1).getType().getSignature());
|
||||||
assertEquals("int *[]", parameters.get(2).getSignature());
|
assertEquals("int *[]", parameters.get(2).getType().getSignature());
|
||||||
assertEquals("int", parameters.get(3).getSignature());
|
assertEquals("int", parameters.get(3).getType().getSignature());
|
||||||
assertEquals("short const *", parameters.get(4).getSignature());
|
assertEquals("short const *", parameters.get(4).getType().getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -935,10 +935,10 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
"undefined Magick::operator<(Magick::Coordinate const &,Magick::Coordinate const &)",
|
"undefined Magick::operator<(Magick::Coordinate const &,Magick::Coordinate const &)",
|
||||||
method.getSignature(false));
|
method.getSignature(false));
|
||||||
|
|
||||||
List<DemangledDataType> parameters = method.getParameters();
|
List<DemangledParameter> parameters = method.getParameters();
|
||||||
assertEquals(2, parameters.size());
|
assertEquals(2, parameters.size());
|
||||||
assertEquals("Magick::Coordinate const &", parameters.get(0).getSignature());
|
assertEquals("Magick::Coordinate const &", parameters.get(0).getType().getSignature());
|
||||||
assertEquals("Magick::Coordinate const &", parameters.get(1).getSignature());
|
assertEquals("Magick::Coordinate const &", parameters.get(1).getType().getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1072,9 +1072,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertEquals("undefined Magick::pageImage::operator()(Magick::Image &)",
|
assertEquals("undefined Magick::pageImage::operator()(Magick::Image &)",
|
||||||
method.getSignature(false));
|
method.getSignature(false));
|
||||||
|
|
||||||
List<DemangledDataType> parameters = method.getParameters();
|
List<DemangledParameter> parameters = method.getParameters();
|
||||||
assertEquals(1, parameters.size());
|
assertEquals(1, parameters.size());
|
||||||
assertEquals("Magick::Image &", parameters.get(0).getSignature());
|
assertEquals("Magick::Image &", parameters.get(0).getType().getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1536,13 +1536,14 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
DemangledFunction df = (DemangledFunction) object;
|
DemangledFunction df = (DemangledFunction) object;
|
||||||
|
|
||||||
List<DemangledDataType> parameters = df.getParameters();
|
List<DemangledParameter> parameters = df.getParameters();
|
||||||
assertEquals("Number of parameters", 1, parameters.size());
|
assertEquals("Number of parameters", 1, parameters.size());
|
||||||
assertEquals("Name of type parsed", "F", parameters.get(0).getName());
|
assertEquals("Name of type parsed", "F", parameters.get(0).getType().getName());
|
||||||
assertEquals("Param Type Name parsed", "WTF", parameters.get(0).getNamespace().toString());
|
assertEquals("Param Type Name parsed", "WTF",
|
||||||
|
parameters.get(0).getType().getNamespace().toString());
|
||||||
assertEquals("Param Template was parsed",
|
assertEquals("Param Template was parsed",
|
||||||
"<WTF::F<void (Core::FileClient &)> (Core::File &)>",
|
"<WTF::F<void (Core::FileClient &)> (Core::File &)>",
|
||||||
parameters.get(0).getTemplate().toString());
|
parameters.get(0).getType().getTemplate().toString());
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"undefined Core::AsyncFile::perform(WTF::F<WTF::F<void (Core::FileClient &)> (Core::File &)> &&)",
|
"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;
|
DemangledFunction df = (DemangledFunction) object;
|
||||||
|
|
||||||
List<DemangledDataType> parameters = df.getParameters();
|
List<DemangledParameter> parameters = df.getParameters();
|
||||||
assertEquals("Number of parameters", 1, parameters.size());
|
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("Name of type parsed", "function", demangParamDT.getName());
|
||||||
assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString());
|
assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString());
|
||||||
|
@ -1601,9 +1602,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
DemangledFunction df = (DemangledFunction) object;
|
DemangledFunction df = (DemangledFunction) object;
|
||||||
|
|
||||||
List<DemangledDataType> parameters = df.getParameters();
|
List<DemangledParameter> parameters = df.getParameters();
|
||||||
assertEquals("Number of parameters", 1, parameters.size());
|
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("Name of type parsed", "function", demangParamDT.getName());
|
||||||
assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString());
|
assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString());
|
||||||
|
@ -1705,9 +1706,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertType(object, DemangledFunction.class);
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
DemangledFunction function = (DemangledFunction) object;
|
DemangledFunction function = (DemangledFunction) object;
|
||||||
List<DemangledDataType> parameters = function.getParameters();
|
List<DemangledParameter> parameters = function.getParameters();
|
||||||
assertEquals(2, parameters.size());
|
assertEquals(2, parameters.size());
|
||||||
assertTrue(parameters.get(1).isVarArgs());
|
assertTrue(parameters.get(1).getType().isVarArgs());
|
||||||
|
|
||||||
assertEquals("undefined testVarArgs(int,...)", object.getSignature(false));
|
assertEquals("undefined testVarArgs(int,...)", object.getSignature(false));
|
||||||
}
|
}
|
||||||
|
|
|
@ -369,7 +369,8 @@ public class MDMangGhidra extends MDMang {
|
||||||
MDArgumentsList args = functionType.getArgumentsList();
|
MDArgumentsList args = functionType.getArgumentsList();
|
||||||
if (functionType.hasArgs() && args != null) {
|
if (functionType.hasArgs() && args != null) {
|
||||||
for (int index = 0; index < args.getNumArgs(); index++) {
|
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()) {
|
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
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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
|
* 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 interface SwiftStructure extends StructConverter {
|
public enum SwiftDemangledBuiltinType {
|
||||||
|
//@formatter:off
|
||||||
public static final String DATA_TYPE_CATEGORY = "/Swift";
|
|
||||||
|
|
||||||
/**
|
Int1,
|
||||||
* Gets the name of the {@link SwiftStructure}
|
Word,
|
||||||
*
|
RawPointer,
|
||||||
* @return The name of the {@link SwiftStructure}
|
Unsupported
|
||||||
*/
|
|
||||||
public String getStructureName();
|
//@formatter:on
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a short description of the {@link SwiftStructure}
|
|
||||||
*
|
|
||||||
* @return A short description of the {@link SwiftStructure}
|
|
||||||
*/
|
|
||||||
public String getDescription();
|
|
||||||
}
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.util.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_AppleSilicon.slaspec||GHIDRA||||END|
|
||||||
data/languages/AARCH64_base_PACoptions.sinc||GHIDRA||||END|
|
data/languages/AARCH64_base_PACoptions.sinc||GHIDRA||||END|
|
||||||
data/languages/AARCH64_ilp32.cspec||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/AARCH64_win.cspec||GHIDRA||||END|
|
||||||
data/languages/AARCH64base.sinc||GHIDRA||||END|
|
data/languages/AARCH64base.sinc||GHIDRA||||END|
|
||||||
data/languages/AARCH64instructions.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="16777228" processor="AARCH64" endian="little" size="64" variant="AppleSilicon" />
|
||||||
<constraint primary="33554444" processor="AARCH64" endian="little" size="32" variant="ilp32" />
|
<constraint primary="33554444" processor="AARCH64" endian="little" size="32" variant="ilp32" />
|
||||||
</constraint>
|
</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 loader="DYLD Cache" compilerSpecID="default">
|
||||||
<constraint primary="AARCH64" processor="AARCH64" endian="little" size="64" variant="AppleSilicon" />
|
<constraint primary="AARCH64" processor="AARCH64" endian="little" size="64" variant="AppleSilicon" />
|
||||||
<constraint primary="ARM64_32" processor="AARCH64" endian="little" size="32" variant="ilp32" />
|
<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">
|
id="AARCH64:LE:64:AppleSilicon">
|
||||||
<description>AppleSilicon ARM v8.5-A LE instructions, LE data, AMX extensions</description>
|
<description>AppleSilicon ARM v8.5-A LE instructions, LE data, AMX extensions</description>
|
||||||
<compiler name="default" spec="AARCH64.cspec" id="default"/>
|
<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"/>
|
||||||
<external_name tool="gnu" name="aarch64:ilp32"/>
|
<external_name tool="gnu" name="aarch64:ilp32"/>
|
||||||
<external_name tool="DWARF.register.mapping.file" name="AARCH64.dwarf"/>
|
<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