mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-06 20:53:55 -05:00
GP-6281: Swift type metadata fixes (#8607)
This commit is contained in:
@@ -35,7 +35,7 @@ public enum SwiftSection {
|
||||
BLOCK_PROTOCS("__swift5_protos", "swift5_protocols", ".sw5prt"),
|
||||
BLOCK_ACFUNCS("__swift5_acfuncs", "swift5_accessible_functions", ".sw5acfn"),
|
||||
BLOCK_MPENUM("__swift5_mpenum", "swift5_mpenum", ".sw5mpen"),
|
||||
BLOCK_TYPES("__swift5_types", "swift5_type_metadata", ".sw5tymd"),
|
||||
BLOCK_TYPES("__swift5_types", "__swift5_types2", "swift5_type_metadata", ".sw5tymd"),
|
||||
BLOCK_ENTRY("__swift5_entry", "swift5_entry", ".sw5entr"),
|
||||
BLOCK_SWIFTAST("__swift_ast", ".swift_ast", "swiftast");
|
||||
|
||||
|
||||
@@ -361,7 +361,11 @@ public class SwiftTypeMetadata {
|
||||
Address blockStart = block.getStart();
|
||||
reader.setPointerIndex(blockStart.getOffset());
|
||||
int i = skipZeroEntries(reader, 0, block.getSize());
|
||||
while (i < block.getSize()) {
|
||||
while (i + MultiPayloadEnumDescriptor.PEEK_SIZE <= block.getSize()) {
|
||||
int contentsSize = MultiPayloadEnumDescriptor.peekContentsSize(reader);
|
||||
if (i + MultiPayloadEnumDescriptor.SIZE + contentsSize > block.getSize()) {
|
||||
break;
|
||||
}
|
||||
monitor.checkCancelled();
|
||||
MultiPayloadEnumDescriptor descriptor = new MultiPayloadEnumDescriptor(reader);
|
||||
mpEnumDescriptors.add(descriptor);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.bin.format.swift.types;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.StructConverter;
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.EnumDataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* Swift {@code InvertibleProtocolKind} values
|
||||
*
|
||||
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/InvertibleProtocols.h">swift/ABI/InvertibleProtocols.h</a>
|
||||
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/InvertibleProtocols.def">swift/ABI/InvertibleProtocols.def</a>
|
||||
*/
|
||||
public enum InvertibleProtocolKind implements StructConverter {
|
||||
|
||||
Copyable(0),
|
||||
Escapable(1);
|
||||
|
||||
private int bit;
|
||||
|
||||
/**
|
||||
* Creates a new {@link InvertibleProtocolKind}
|
||||
*
|
||||
* @param bit The bit number that represents the kind
|
||||
*/
|
||||
private InvertibleProtocolKind(int bit) {
|
||||
this.bit = bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the bit number that represents the kind}
|
||||
*/
|
||||
public int getBit() {
|
||||
return bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the {@link Set} of {@link InvertibleProtocolKind}s that map to the given kind value}
|
||||
*
|
||||
* @param value The kind value to get the value of
|
||||
*/
|
||||
public static Set<InvertibleProtocolKind> valueOf(short value) {
|
||||
Set<InvertibleProtocolKind> set = new HashSet<>();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
final int bitPos = i;
|
||||
int bit = (value >> bitPos) & 0x1;
|
||||
if (bit != 0) {
|
||||
Arrays.stream(values())
|
||||
.filter(e -> e.getBit() == bitPos)
|
||||
.findFirst()
|
||||
.ifPresent(set::add);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
EnumDataType dt = new EnumDataType(SwiftTypeMetadataStructure.CATEGORY_PATH,
|
||||
InvertibleProtocolKind.class.getSimpleName(), 2);
|
||||
for (InvertibleProtocolKind kind : values()) {
|
||||
dt.add(kind.name(), 1 << kind.getBit());
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.bin.format.swift.types;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.format.swift.SwiftTypeMetadataStructure;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.StructureDataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* Represents a Swift {@code InvertibleProtocolSet} structure
|
||||
*
|
||||
* @see <a href="https://github.com/swiftlang/swift/blob/main/include/swift/ABI/InvertibleProtocols.h">swift/ABI/InvertibleProtocols.h</a>
|
||||
*/
|
||||
public class InvertibleProtocolSet extends SwiftTypeMetadataStructure {
|
||||
|
||||
/**
|
||||
* The size (in bytes) of a {@link InvertibleProtocolSet} structure
|
||||
*/
|
||||
public static final int SIZE = 2;
|
||||
|
||||
private short bits;
|
||||
|
||||
/**
|
||||
* Create a new {@link InvertibleProtocolSet}
|
||||
*
|
||||
* @param reader A {@link BinaryReader} positioned at the start of the structure
|
||||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public InvertibleProtocolSet(BinaryReader reader) throws IOException {
|
||||
super(reader.getPointerIndex());
|
||||
bits = reader.readNextShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the raw bits}
|
||||
*/
|
||||
public short getRawBits() {
|
||||
return bits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStructureName() {
|
||||
return InvertibleProtocolSet.class.getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "invertible protocol set";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
StructureDataType struct = new StructureDataType(CATEGORY_PATH, getStructureName(), 0);
|
||||
struct.add(InvertibleProtocolKind.values()[0].toDataType(), "bits", "The storage bits");
|
||||
return struct;
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,11 @@ public final class MultiPayloadEnumDescriptor extends SwiftTypeMetadataStructure
|
||||
*/
|
||||
public static final int SIZE = 4;
|
||||
|
||||
/**
|
||||
* How many bytes it requires to peek at size of the {@code contents} array
|
||||
*/
|
||||
public static final int PEEK_SIZE = 8;
|
||||
|
||||
private String typeName;
|
||||
private int[] contents;
|
||||
|
||||
@@ -70,12 +75,31 @@ public final class MultiPayloadEnumDescriptor extends SwiftTypeMetadataStructure
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The size of the contents in bytes}
|
||||
* {@return the size of the contents in bytes}
|
||||
*/
|
||||
public long getContentsSize() {
|
||||
return contents.length * Integer.BYTES;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the size of the contents in bytes, without reading the contents}
|
||||
* <p>
|
||||
* This method will leave the {@link BinaryReader}'s position unaffected.
|
||||
*
|
||||
* @param reader A {@link BinaryReader} positioned at the start of the structure
|
||||
* @throws IOException if there was an IO-related problem creating the structure
|
||||
*/
|
||||
public static int peekContentsSize(BinaryReader reader) throws IOException {
|
||||
long origIndex = reader.getPointerIndex();
|
||||
try {
|
||||
reader.readNext(SwiftUtils::relativeString);
|
||||
return (reader.readNextInt() >> 16) & 0xffff;
|
||||
}
|
||||
finally {
|
||||
reader.setPointerIndex(origIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStructureName() {
|
||||
return MultiPayloadEnumDescriptor.class.getSimpleName();
|
||||
|
||||
@@ -51,6 +51,7 @@ public final class TargetClassDescriptor extends TargetTypeContextDescriptor {
|
||||
private TargetOverrideTableHeader overrideHeader;
|
||||
private List<TargetMethodOverrideDescriptor> methodOverrideDescriptors = new ArrayList<>();
|
||||
private TargetObjCResilientClassStubInfo objcResilientClassStub;
|
||||
private InvertibleProtocolSet invertibleProtocolSet;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TargetClassDescriptor}
|
||||
@@ -113,7 +114,7 @@ public final class TargetClassDescriptor extends TargetTypeContextDescriptor {
|
||||
}
|
||||
|
||||
if (flags.hasInvertableProtocols()) {
|
||||
throw new IOException("Unimplemented InvertibleProtocolSet detected.");
|
||||
invertibleProtocolSet = new InvertibleProtocolSet(reader);
|
||||
}
|
||||
|
||||
if (!flags.isGeneric() &&
|
||||
@@ -256,6 +257,13 @@ public final class TargetClassDescriptor extends TargetTypeContextDescriptor {
|
||||
return objcResilientClassStub;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the {@link InvertibleProtocolSet}, or {@code null} if it doens't exist}
|
||||
*/
|
||||
public InvertibleProtocolSet getInvertibleProtocolSet() {
|
||||
return invertibleProtocolSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
|
||||
List<SwiftTypeMetadataStructure> ret = new ArrayList<>();
|
||||
@@ -283,6 +291,9 @@ public final class TargetClassDescriptor extends TargetTypeContextDescriptor {
|
||||
if (objcResilientClassStub != null) {
|
||||
ret.add(objcResilientClassStub);
|
||||
}
|
||||
if (invertibleProtocolSet != null) {
|
||||
ret.add(invertibleProtocolSet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
|
||||
private TargetTypeGenericContextDescriptorHeader genericHeader;
|
||||
private TargetSingletonMetadataInitialization singleton;
|
||||
private TargetForeignMetadataInitialization foreign;
|
||||
private InvertibleProtocolSet invertibleProtocolSet;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TargetEnumDescriptor}
|
||||
@@ -72,7 +73,7 @@ public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
|
||||
}
|
||||
|
||||
if (flags.hasInvertableProtocols()) {
|
||||
throw new IOException("Unimplemented InvertibleProtocolSet detected.");
|
||||
invertibleProtocolSet = new InvertibleProtocolSet(reader);
|
||||
}
|
||||
|
||||
if (!flags.isGeneric() &&
|
||||
@@ -122,6 +123,13 @@ public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
|
||||
return foreign;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the {@link InvertibleProtocolSet}, or {@code null} if it doens't exist}
|
||||
*/
|
||||
public InvertibleProtocolSet getInvertibleProtocolSet() {
|
||||
return invertibleProtocolSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
|
||||
List<SwiftTypeMetadataStructure> ret = new ArrayList<>();
|
||||
@@ -135,6 +143,9 @@ public final class TargetEnumDescriptor extends TargetTypeContextDescriptor {
|
||||
if (foreign != null) {
|
||||
ret.add(foreign);
|
||||
}
|
||||
if (invertibleProtocolSet != null) {
|
||||
ret.add(invertibleProtocolSet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ public final class TargetStructDescriptor extends TargetTypeContextDescriptor {
|
||||
private TargetTypeGenericContextDescriptorHeader genericHeader;
|
||||
private TargetSingletonMetadataInitialization singleton;
|
||||
private TargetForeignMetadataInitialization foreign;
|
||||
private InvertibleProtocolSet invertibleProtocolSet;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TargetStructDescriptor}
|
||||
@@ -72,7 +73,7 @@ public final class TargetStructDescriptor extends TargetTypeContextDescriptor {
|
||||
}
|
||||
|
||||
if (flags.hasInvertableProtocols()) {
|
||||
throw new IOException("Unimplemented InvertibleProtocolSet detected.");
|
||||
invertibleProtocolSet = new InvertibleProtocolSet(reader);
|
||||
}
|
||||
|
||||
if (!flags.isGeneric() &&
|
||||
@@ -121,6 +122,13 @@ public final class TargetStructDescriptor extends TargetTypeContextDescriptor {
|
||||
return foreign;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the {@link InvertibleProtocolSet}, or {@code null} if it doens't exist}
|
||||
*/
|
||||
public InvertibleProtocolSet getInvertibleProtocolSet() {
|
||||
return invertibleProtocolSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SwiftTypeMetadataStructure> getTrailingObjects() {
|
||||
List<SwiftTypeMetadataStructure> ret = new ArrayList<>();
|
||||
@@ -134,6 +142,9 @@ public final class TargetStructDescriptor extends TargetTypeContextDescriptor {
|
||||
if (foreign != null) {
|
||||
ret.add(foreign);
|
||||
}
|
||||
if (invertibleProtocolSet != null) {
|
||||
ret.add(invertibleProtocolSet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user