| 805 | } |
| 806 | |
| 807 | void ObjCProcessor::ReadMethodList(ObjCReader* reader, ClassBase& cls, std::string_view name, view_ptr_t start) |
| 808 | { |
| 809 | // Lower two bits indicate the type of method list. |
| 810 | switch (start & 0b11) { |
| 811 | case 0: |
| 812 | break; |
| 813 | case 1: |
| 814 | return ReadListOfMethodLists(reader, cls, name, start - 1); |
| 815 | default: |
| 816 | m_logger->LogDebug("ReadMethodList: Unknown method list type at 0x%llx: %d", start, start & 0x3); |
| 817 | return; |
| 818 | } |
| 819 | |
| 820 | reader->Seek(start); |
| 821 | method_list_t head; |
| 822 | head.entsizeAndFlags = reader->Read32(); |
| 823 | head.count = reader->Read32(); |
| 824 | |
| 825 | if (head.count > 0x1000) |
| 826 | { |
| 827 | m_logger->LogError("Method list at 0x%llx has an invalid count of 0x%x", start, head.count); |
| 828 | return; |
| 829 | } |
| 830 | |
| 831 | uint64_t pointerSize = m_data->GetAddressSize(); |
| 832 | bool relativeOffsets = (head.entsizeAndFlags & 0xFFFF0000) & 0x80000000; |
| 833 | bool directSelectors = (head.entsizeAndFlags & 0xFFFF0000) & 0x40000000; |
| 834 | auto methodSize = relativeOffsets ? 12 : pointerSize * 3; |
| 835 | DefineObjCSymbol(DataSymbol, m_typeNames.methodList, "method_list_" + std::string(name), start, true); |
| 836 | |
| 837 | for (unsigned i = 0; i < head.count; i++) |
| 838 | { |
| 839 | try |
| 840 | { |
| 841 | Method method; |
| 842 | auto cursor = start + sizeof(method_list_t) + (i * methodSize); |
| 843 | reader->Seek(cursor); |
| 844 | method_t meth; |
| 845 | // workflow_objc support |
| 846 | uint64_t selRefAddr = 0; |
| 847 | uint64_t selAddr = 0; |
| 848 | // -- |
| 849 | if (relativeOffsets) |
| 850 | { |
| 851 | GetRelativeMethod(reader, meth); |
| 852 | } |
| 853 | else |
| 854 | { |
| 855 | meth.name = ReadPointerAccountingForRelocations(reader); |
| 856 | meth.types = ReadPointerAccountingForRelocations(reader); |
| 857 | meth.imp = ReadPointerAccountingForRelocations(reader); |
| 858 | } |
| 859 | if (!relativeOffsets || directSelectors) |
| 860 | { |
| 861 | reader->Seek(meth.name); |
| 862 | selAddr = meth.name; |
| 863 | method.name = reader->ReadCString(); |
| 864 | reader->Seek(meth.types); |
nothing calls this directly
no test coverage detected