diff --git a/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/OCClassFieldAnalyzer.kt b/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/OCClassFieldAnalyzer.kt index c45042d..86e92c6 100644 --- a/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/OCClassFieldAnalyzer.kt +++ b/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/OCClassFieldAnalyzer.kt @@ -6,8 +6,7 @@ import ghidra.app.services.AnalyzerType import ghidra.app.util.importer.MessageLog import ghidra.program.model.address.AddressSetView import ghidra.program.model.address.GenericAddress -import ghidra.program.model.data.DataType -import ghidra.program.model.data.Structure +import ghidra.program.model.data.* import ghidra.program.model.listing.Data import ghidra.program.model.listing.Program import ghidra.program.model.scalar.Scalar @@ -59,6 +58,7 @@ class OCClassFieldAnalyzer : AbstractAnalyzer(NAME, DESCRIPTION, AnalyzerType.DA program.withTransaction("Apply fields.") { for (it in fieldLists) { + monitor.checkCancelled() val definedClassStruct = typeResolver.tryResolveDefinedStruct(it.classSymbol.name) as Structure? if (definedClassStruct == null) { log.appendMsg("Couldn't find defined structure for ${it.classSymbol.name} ivar list.") @@ -66,14 +66,30 @@ class OCClassFieldAnalyzer : AbstractAnalyzer(NAME, DESCRIPTION, AnalyzerType.DA } it.ivars.forEach { field -> - val fieldType = field.type.let { - typeResolver.parseEncoded(it) ?: DataType.DEFAULT - } - - println("${field.name}: ${fieldType.name}") val fieldSize = field.size.toInt() + + val fieldType = field.type.let { typeString -> + val resolvedType = typeResolver.parseEncoded(typeString) + + if (resolvedType == null ){ + Undefined.getUndefinedDataType(fieldSize) + } + // There is some bug where a field is typed as int with size 4, but Ghidra later + // treats an int as size 8, and then fails to decompile functions using this field + // to fix this we change them to short and unsigned short respectively. + else if (resolvedType.name == "int" && fieldSize == 4) { + ShortDataType.dataType + } + else if (resolvedType.name == "uint" && fieldSize == 8) { + UnsignedShortDataType.dataType + } + else { + resolvedType + } + } + definedClassStruct.insertAtOffset(field.offset, fieldType, fieldSize, field.name, null) } diff --git a/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/OCRetypeRecvAnalyzer.kt b/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/OCRetypeRecvAnalyzer.kt index 9bfb2f4..08ce60f 100644 --- a/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/OCRetypeRecvAnalyzer.kt +++ b/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/OCRetypeRecvAnalyzer.kt @@ -43,10 +43,8 @@ class OCRetypeRecvAnalyzer : AbstractAnalyzer(NAME, DESCRIPTION, AnalyzerType.FU program.withTransaction("Apply receiver types to class methods.") { classMethods.forEach { (typedef, methods) -> - println("CLASS ${typedef.name}") for (method in methods) { - println(" METHOD ${method.name}") if (method.parameterCount == 0) { continue diff --git a/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/TypeResolver.kt b/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/TypeResolver.kt index 6fff969..f207788 100644 --- a/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/TypeResolver.kt +++ b/src/main/java/lol/fairplay/ghidraapple/analysis/objcclasses/TypeResolver.kt @@ -34,12 +34,14 @@ class TypeResolver(val program: Program) { // this will be more robust in the future. // reference: https://nshipster.com/type-encodings/ - println("input: $encodedType") + if (encodedType.isEmpty()) + return null when (encodedType[0]) { '@' -> { - if (encodedType.length == 1) + if (encodedType.length == 1 || encodedType == "@?") return dtm.getDataType("/_objc2_/ID") + // expect a defined type structure return tryResolveTypedef(encodedType.substring(2, encodedType.length - 1)) }