@@ -918,8 +918,11 @@ void ObjCProcessor::LoadProtocols(ObjCReader* reader, Ref<Section> listSection)
918918 }
919919}
920920
921- void ObjCProcessor::GetRelativeMethod (ObjCReader* reader, method_t & meth)
921+ void ObjCProcessor::GetRelativeMethod (ObjCReader* reader, method_t & meth, bool typesAreOffsetsFromSelectorBase )
922922{
923+ // `typesAreOffsetsFromSelectorBase` is only relevant for shared caches
924+ (void )typesAreOffsetsFromSelectorBase;
925+
923926 uint64_t offset = reader->GetOffset ();
924927 meth.name = offset + reader->ReadS32 ();
925928
@@ -980,15 +983,16 @@ void ObjCProcessor::ReadMethodList(ObjCReader* reader, ClassBase& cls, std::stri
980983 uint64_t pointerSize = m_data->GetAddressSize ();
981984 bool relativeOffsets = (head.entsizeAndFlags & 0xFFFF0000 ) & 0x80000000 ;
982985 bool directSelectors = (head.entsizeAndFlags & 0xFFFF0000 ) & 0x40000000 ;
986+ bool typesAreOffsetsFromSelectorBase = (head.entsizeAndFlags & 0xFFFF0000 ) & 0x20000000 ;
983987 auto methodSize = relativeOffsets ? 12 : pointerSize * 3 ;
984988 DefineObjCSymbol (DataSymbol, m_typeNames.methodList , " method_list_" + std::string (name), start, true );
985989
986990 for (unsigned i = 0 ; i < head.count ; i++)
987991 {
992+ auto cursor = start + sizeof (method_list_t ) + (i * methodSize);
988993 try
989994 {
990995 Method method;
991- auto cursor = start + sizeof (method_list_t ) + (i * methodSize);
992996 reader->Seek (cursor);
993997 method_t meth;
994998 // workflow_objc support
@@ -997,7 +1001,7 @@ void ObjCProcessor::ReadMethodList(ObjCReader* reader, ClassBase& cls, std::stri
9971001 // --
9981002 if (relativeOffsets)
9991003 {
1000- GetRelativeMethod (reader, meth);
1004+ GetRelativeMethod (reader, meth, typesAreOffsetsFromSelectorBase );
10011005 }
10021006 else
10031007 {
@@ -1050,8 +1054,12 @@ void ObjCProcessor::ReadMethodList(ObjCReader* reader, ClassBase& cls, std::stri
10501054 m_selRefToImplementations[selRefAddr].push_back (meth.imp );
10511055 // --
10521056
1053- DefineObjCSymbol (DataSymbol, relativeOffsets ? m_typeNames.methodEntry : m_typeNames.method ,
1054- " method_" + method.name , cursor, true );
1057+ QualifiedName methodTypeName = m_typeNames.method ;
1058+ if (relativeOffsets)
1059+ methodTypeName = typesAreOffsetsFromSelectorBase && !m_typeNames.methodEntryTypeOffsets .IsEmpty ()
1060+ ? m_typeNames.methodEntryTypeOffsets
1061+ : m_typeNames.methodEntry ;
1062+ DefineObjCSymbol (DataSymbol, methodTypeName, " method_" + method.name , cursor, true );
10551063 method.imp = meth.imp ;
10561064 cls.methodList [cursor] = method;
10571065 m_localMethods[cursor] = method;
@@ -1061,10 +1069,14 @@ void ObjCProcessor::ReadMethodList(ObjCReader* reader, ClassBase& cls, std::stri
10611069 if (selRefAddr)
10621070 m_data->AddDataReference (selRefAddr, meth.imp );
10631071 }
1072+ catch (const std::exception& ex)
1073+ {
1074+ m_logger->LogErrorF (
1075+ " Failed to process a method at offset {:#x} in method list \" {}\" : {}" , cursor, name, ex.what ());
1076+ }
10641077 catch (...)
10651078 {
1066- m_logger->LogError (
1067- " Failed to process a method at offset 0x%llx" , start + sizeof (method_list_t ) + (i * methodSize));
1079+ m_logger->LogErrorF (" Failed to process a method at offset {:#x} in method list \" {}\" " , cursor, name);
10681080 }
10691081 }
10701082}
@@ -1512,6 +1524,23 @@ void ObjCProcessor::ProcessObjCData()
15121524 auto type = finalizeStructureBuilder (m_data, methodEntry, " objc_method_entry_t" );
15131525 m_typeNames.methodEntry = type.first ;
15141526
1527+ // Shared caches built with type offsets store the `types` field as an offset from the same base address as
1528+ // relative selectors. That base address is only known for shared caches, so the struct is only defined for them.
1529+ if (relativeSelectorBaseOffset)
1530+ {
1531+ auto relativeTypesPtrName = defineTypedef (m_data, {" rel_types" },
1532+ TypeBuilder::PointerType (4 , Type::PointerType (addrSize, Type::IntegerType (1 , false )))
1533+ .SetPointerBase (RelativeToConstantPointerBaseType, relativeSelectorBaseOffset)
1534+ .Finalize ());
1535+
1536+ StructureBuilder methodEntryTypeOffsets;
1537+ methodEntryTypeOffsets.AddMember (Type::NamedType (m_data, relativeSelectorPtrName), " name" );
1538+ methodEntryTypeOffsets.AddMember (Type::NamedType (m_data, relativeTypesPtrName), " types" );
1539+ methodEntryTypeOffsets.AddMember (Type::NamedType (m_data, relativeIMPPtrName), " imp" );
1540+ type = finalizeStructureBuilder (m_data, methodEntryTypeOffsets, " objc_method_entry_type_offsets_t" );
1541+ m_typeNames.methodEntryTypeOffsets = type.first ;
1542+ }
1543+
15151544 StructureBuilder method;
15161545 method.AddMember (Type::PointerType (addrSize, Type::IntegerType (1 , true )), " name" );
15171546 method.AddMember (Type::PointerType (addrSize, Type::IntegerType (1 , true )), " types" );
0 commit comments