@@ -340,7 +340,8 @@ void ObjCProcessor::LoadClasses(BinaryReader* reader, Ref<Section> classPtrSecti
340340 auto size = classPtrSection->GetEnd () - classPtrSection->GetStart ();
341341 if (size == 0 )
342342 return ;
343- auto ptrCount = size / m_data->GetAddressSize ();
343+ auto ptrSize = m_data->GetAddressSize ();
344+ auto ptrCount = size / ptrSize;
344345
345346 auto classPtrSectionStart = classPtrSection->GetStart ();
346347 for (size_t i = 0 ; i < ptrCount; i++)
@@ -433,6 +434,19 @@ void ObjCProcessor::LoadClasses(BinaryReader* reader, Ref<Section> classPtrSecti
433434 DefineObjCSymbol (BNSymbolType::DataSymbol, m_typeNames.cls , " cls_" + name, classPtr, true );
434435 DefineObjCSymbol (BNSymbolType::DataSymbol, m_typeNames.classRO , " cls_ro_" + name, classROPtr, true );
435436 DefineObjCSymbol (BNSymbolType::DataSymbol, Type::ArrayType (Type::IntegerType (1 , true ), name.size ()+1 ), " clsName_" + name, classRO.name , true );
437+ if (classRO.baseProtocols )
438+ {
439+ DefineObjCSymbol (BNSymbolType::DataSymbol, Type::NamedType (m_data, m_typeNames.protocolList ),
440+ " clsProtocols_" + name, classRO.baseProtocols , true );
441+ reader->Seek (classRO.baseProtocols );
442+ uint32_t count = reader->Read64 ();
443+ view_ptr_t addr = reader->GetOffset ();
444+ for (uint32_t j = 0 ; j < count; j++)
445+ {
446+ m_data->DefineDataVariable (addr, Type::PointerType (ptrSize, Type::NamedType (m_data, m_typeNames.protocol )));
447+ addr += ptrSize;
448+ }
449+ }
436450
437451 if (clsStruct.isa )
438452 {
@@ -631,6 +645,130 @@ void ObjCProcessor::LoadCategories(BinaryReader* reader, Ref<Section> classPtrSe
631645 }
632646}
633647
648+ void ObjCProcessor::LoadProtocols (BinaryReader* reader, Ref<Section> listSection)
649+ {
650+ if (!listSection)
651+ return ;
652+ auto size = listSection->GetEnd () - listSection->GetStart ();
653+ if (size == 0 )
654+ return ;
655+ auto ptrSize = m_data->GetAddressSize ();
656+
657+ auto listSectionStart = listSection->GetStart ();
658+ auto listSectionEnd = listSection->GetEnd ();
659+
660+ auto protocolType = Type::NamedType (m_data, m_typeNames.protocol );
661+ auto ptrType = Type::PointerType (m_data->GetDefaultArchitecture (), protocolType);
662+ for (size_t i = listSectionStart; i < listSectionEnd; i += ptrSize)
663+ {
664+ protocol_t protocol;
665+ reader->Seek (i);
666+ auto protocolLocation = ReadPointerAccountingForRelocations (reader);
667+ reader->Seek (protocolLocation);
668+
669+ try
670+ {
671+ protocol.isa = ReadPointerAccountingForRelocations (reader);
672+ protocol.mangledName = ReadPointerAccountingForRelocations (reader);
673+ protocol.protocols = ReadPointerAccountingForRelocations (reader);
674+ protocol.instanceMethods = ReadPointerAccountingForRelocations (reader);
675+ protocol.classMethods = ReadPointerAccountingForRelocations (reader);
676+ protocol.optionalInstanceMethods = ReadPointerAccountingForRelocations (reader);
677+ protocol.optionalClassMethods = ReadPointerAccountingForRelocations (reader);
678+ protocol.instanceProperties = ReadPointerAccountingForRelocations (reader);
679+ }
680+ catch (ReadException& ex)
681+ {
682+ m_logger->LogError (" Failed to read protocol pointed to by 0x%llx" , i);
683+ continue ;
684+ }
685+
686+ std::string protocolName;
687+ try
688+ {
689+ reader->Seek (protocol.mangledName );
690+ protocolName = reader->ReadCString ();
691+ DefineObjCSymbol (BNSymbolType::DataSymbol, Type::ArrayType (Type::IntegerType (1 , true ), protocolName.size () + 1 ),
692+ " protocolName_" + protocolName, protocol.mangledName , true );
693+ }
694+ catch (ReadException& ex)
695+ {
696+ m_logger->LogError (
697+ " Failed to read protocol name for protocol at 0x%llx. Using base address as stand-in protocol name" ,
698+ protocolLocation);
699+ protocolName = std::to_string (protocolLocation);
700+ }
701+
702+ Protocol protocolClass;
703+ protocolClass.name = protocolName;
704+ DefineObjCSymbol (BNSymbolType::DataSymbol, ptrType, " protocolPtr_" + protocolName, i, true );
705+ DefineObjCSymbol (BNSymbolType::DataSymbol, protocolType, " protocol_" + protocolName, protocolLocation, true );
706+ if (protocol.protocols )
707+ {
708+ DefineObjCSymbol (BNSymbolType::DataSymbol, Type::NamedType (m_data, m_typeNames.protocolList ),
709+ " protoProtocols_" + protocolName, protocol.protocols , true );
710+ reader->Seek (protocol.protocols );
711+ uint32_t count = reader->Read64 ();
712+ view_ptr_t addr = reader->GetOffset ();
713+ for (uint32_t j = 0 ; j < count; j++)
714+ {
715+ m_data->DefineDataVariable (addr, Type::PointerType (ptrSize, Type::NamedType (m_data, m_typeNames.protocol )));
716+ addr += ptrSize;
717+ }
718+ }
719+
720+ if (protocol.instanceMethods )
721+ {
722+ try
723+ {
724+ ReadMethodList (reader, protocolClass.instanceMethods , protocolName, protocol.instanceMethods );
725+ }
726+ catch (ReadException& ex)
727+ {
728+ m_logger->LogError (
729+ " Failed to read the instance method list for protocol pointed to by 0x%llx" , protocolLocation);
730+ }
731+ }
732+ if (protocol.classMethods )
733+ {
734+ try
735+ {
736+ ReadMethodList (reader, protocolClass.classMethods , protocolName, protocol.classMethods );
737+ }
738+ catch (ReadException& ex)
739+ {
740+ m_logger->LogError (
741+ " Failed to read the class method list for protocol pointed to by 0x%llx" , protocolLocation);
742+ }
743+ }
744+ if (protocol.optionalInstanceMethods )
745+ {
746+ try
747+ {
748+ ReadMethodList (reader, protocolClass.optionalInstanceMethods , protocolName, protocol.optionalInstanceMethods );
749+ }
750+ catch (ReadException& ex)
751+ {
752+ m_logger->LogError (
753+ " Failed to read the optional instance method list for protocol pointed to by 0x%llx" , protocolLocation);
754+ }
755+ }
756+ if (protocol.optionalClassMethods )
757+ {
758+ try
759+ {
760+ ReadMethodList (reader, protocolClass.optionalClassMethods , protocolName, protocol.optionalClassMethods );
761+ }
762+ catch (ReadException& ex)
763+ {
764+ m_logger->LogError (
765+ " Failed to read the optional class method list for protocol pointed to by 0x%llx" , protocolLocation);
766+ }
767+ }
768+ m_protocols[protocolLocation] = protocolClass;
769+ }
770+ }
771+
634772void ObjCProcessor::ReadMethodList (BinaryReader* reader, ClassBase& cls, std::string name, view_ptr_t start)
635773{
636774 reader->Seek (start);
@@ -755,6 +893,10 @@ void ObjCProcessor::ReadIvarList(BinaryReader* reader, ClassBase& cls, std::stri
755893 ivar.type = reader->ReadCString ();
756894
757895 DefineObjCSymbol (DataSymbol, m_typeNames.ivar , " ivar_" + ivar.name , cursor, true );
896+ DefineObjCSymbol (DataSymbol, Type::ArrayType (Type::IntegerType (1 , true ), ivar.name .size () + 1 ),
897+ " ivarName_" + ivar.name , ivarStruct.name , true );
898+ DefineObjCSymbol (DataSymbol, Type::ArrayType (Type::IntegerType (1 , true ), ivar.type .size () + 1 ),
899+ " ivarType_" + ivar.name , ivarStruct.type , true );
758900
759901 cls.ivarList [cursor] = ivar;
760902 }
@@ -996,6 +1138,24 @@ void ObjCProcessor::PostProcessObjCSections(BinaryReader* reader)
9961138 }
9971139 }
9981140 }
1141+ if (auto protoRefs = m_data->GetSectionByName (" __objc_protorefs" ))
1142+ {
1143+ auto start = protoRefs->GetStart ();
1144+ auto end = protoRefs->GetEnd ();
1145+ auto type = Type::PointerType (ptrSize, Type::NamedType (m_data, m_typeNames.protocol ));
1146+ for (view_ptr_t i = start; i < end; i += ptrSize)
1147+ {
1148+ reader->Seek (i);
1149+ auto protoLoc = ReadPointerAccountingForRelocations (reader);
1150+ if (const auto & it = m_protocols.find (protoLoc); it != m_protocols.end ())
1151+ {
1152+ auto & proto = it->second ;
1153+ std::string name = proto.name ;
1154+ if (!name.empty ())
1155+ DefineObjCSymbol (DataSymbol, type, " protoRef_" + name, i, true );
1156+ }
1157+ }
1158+ }
9991159 if (auto ivars = m_data->GetSectionByName (" __objc_ivar" ))
10001160 {
10011161 auto start = ivars->GetStart ();
@@ -1189,6 +1349,10 @@ void ObjCProcessor::ProcessObjCData()
11891349 type = finalizeStructureBuilder (m_data, ivarList, " objc_ivar_list_t" );
11901350 m_typeNames.ivarList = type.first ;
11911351
1352+ StructureBuilder protocolListBuilder;
1353+ protocolListBuilder.AddMember (Type::IntegerType (addrSize, false ), " count" );
1354+ m_typeNames.protocolList = finalizeStructureBuilder (m_data, protocolListBuilder, " objc_protocol_list_t" ).first ;
1355+
11921356 StructureBuilder classROBuilder;
11931357 classROBuilder.AddMember (Type::IntegerType (4 , false ), " flags" );
11941358 classROBuilder.AddMember (Type::IntegerType (4 , false ), " start" );
@@ -1198,7 +1362,7 @@ void ObjCProcessor::ProcessObjCData()
11981362 classROBuilder.AddMember (Type::PointerType (addrSize, Type::VoidType ()), " ivar_layout" );
11991363 classROBuilder.AddMember (Type::PointerType (addrSize, Type::IntegerType (1 , true )), " name" );
12001364 classROBuilder.AddMember (Type::PointerType (addrSize, Type::NamedType (m_data, m_typeNames.methodList )), " methods" );
1201- classROBuilder.AddMember (Type::PointerType (addrSize, Type::VoidType ( )), " protocols" );
1365+ classROBuilder.AddMember (Type::PointerType (addrSize, Type::NamedType (m_data, m_typeNames. protocolList )), " protocols" );
12021366 classROBuilder.AddMember (Type::PointerType (addrSize, Type::NamedType (m_data, m_typeNames.ivarList )), " ivars" );
12031367 classROBuilder.AddMember (Type::PointerType (addrSize, Type::VoidType ()), " weak_ivar_layout" );
12041368 classROBuilder.AddMember (Type::PointerType (addrSize, Type::VoidType ()), " properties" );
@@ -1236,6 +1400,18 @@ void ObjCProcessor::ProcessObjCData()
12361400 categoryBuilder.AddMember (Type::PointerType (addrSize, Type::VoidType ()), " properties" );
12371401 m_typeNames.category = finalizeStructureBuilder (m_data, categoryBuilder, " objc_category_t" ).first ;
12381402
1403+ StructureBuilder protocolBuilder;
1404+ protocolBuilder.AddMember (Type::PointerType (addrSize, Type::VoidType ()), " isa" );
1405+ protocolBuilder.AddMember (Type::PointerType (addrSize, Type::IntegerType (1 , true )), " mangledName" );
1406+ protocolBuilder.AddMember (Type::PointerType (addrSize, Type::NamedType (m_data, m_typeNames.protocolList )), " protocols" );
1407+ protocolBuilder.AddMember (Type::PointerType (addrSize, Type::NamedType (m_data, m_typeNames.methodList )), " instanceMethods" );
1408+ protocolBuilder.AddMember (Type::PointerType (addrSize, Type::NamedType (m_data, m_typeNames.methodList )), " classMethods" );
1409+ protocolBuilder.AddMember (Type::PointerType (addrSize, Type::NamedType (m_data, m_typeNames.methodList )), " optionalInstanceMethods" );
1410+ protocolBuilder.AddMember (Type::PointerType (addrSize, Type::NamedType (m_data, m_typeNames.methodList )), " optionalClassMethods" );
1411+ protocolBuilder.AddMember (Type::PointerType (addrSize, Type::VoidType ()), " instanceProperties" );
1412+ protocolBuilder.AddMember (Type::IntegerType (4 , false ), " size" );
1413+ protocolBuilder.AddMember (Type::IntegerType (4 , false ), " flags" );
1414+ m_typeNames.protocol = finalizeStructureBuilder (m_data, protocolBuilder, " objc_protocol_t" ).first ;
12391415
12401416 auto reader = BinaryReader (m_data);
12411417 m_data->BeginBulkModifySymbols ();
@@ -1253,6 +1429,9 @@ void ObjCProcessor::ProcessObjCData()
12531429 for (auto & [_, cat] : m_categories)
12541430 ApplyMethodTypes (cat);
12551431
1432+ if (auto protoList = m_data->GetSectionByName (" __objc_protolist" ))
1433+ LoadProtocols (&reader, protoList);
1434+
12561435 PostProcessObjCSections (&reader);
12571436
12581437 m_symbolQueue->Process ();
0 commit comments