Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | /* * Copyright (c) 2021 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef mach_o_ObjC_h #define mach_o_ObjC_h #include "MachODefines.h" namespace mach_o { /*! * @class ObjCClass * * @abstract * Class to encapsulate accessing (and one day building) objc classes */ struct VIS_HIDDEN ObjCClass { // Note a class looks like this to libobjc: // template<typename PtrTy> // struct class_t { // PtrTy isaVMAddr; // PtrTy superclassVMAddr; // PtrTy methodCacheBuckets; // PtrTy methodCacheProperties; // aka vtable // PtrTy dataVMAddrAndFastFlags; // // This field is only present if this is a Swift object, ie, has the Swift // // fast bits set // uint32_t swiftClassFlags; // }; // Note that @objc Swift classes use alt_entry to add data before the ObjC Class // The actual objc class_t above will be an alt_entry in to the atom static constexpr uint32_t getOffsetToISA(bool is64, uint32_t swiftPreamble) { return swiftPreamble + 0; } static constexpr uint32_t getOffsetToSuperclass(bool is64, uint32_t swiftPreamble) { return swiftPreamble + (is64 ? 0x08 : 0x04); } static constexpr uint32_t getOffsetToMethodCache(bool is64, uint32_t swiftPreamble) { return swiftPreamble + (is64 ? 0x10 : 0x08); } static constexpr uint32_t getOffsetToMethodCacheProperies(bool is64, uint32_t swiftPreamble) { return swiftPreamble + (is64 ? 0x18 : 0x0C); } static constexpr uint32_t getOffsetToData(bool is64, uint32_t swiftPreamble) { return swiftPreamble + (is64 ? 0x20 : 0x10); } }; /*! * @class ObjCClassReadOnlyData * * @abstract * Class to encapsulate accessing (and one day building) objc class read-only data */ struct VIS_HIDDEN ObjCClassReadOnlyData { // Data is a pointer to the read only data for the class, ie, one of these according to objc: // template<typename PtrTy> // struct data_t { // uint32_t flags; // uint32_t instanceStart; // // Note there is 4-bytes of alignment padding between instanceSize and ivarLayout // // on 64-bit archs, but no padding on 32-bit archs. // // This union is a way to model that. // union { // uint32_t instanceSize; // PtrTy pad; // } instanceSize; // PtrTy ivarLayoutVMAddr; // PtrTy nameVMAddr; // PtrTy baseMethodsVMAddr; // PtrTy baseProtocolsVMAddr; // PtrTy ivarsVMAddr; // PtrTy weakIvarLayoutVMAddr; // PtrTy basePropertiesVMAddr; // }; static constexpr uint32_t getOffsetToName(bool is64) { return is64 ? 0x18 : 0x10; } static constexpr uint32_t getOffsetToBaseMethods(bool is64) { return is64 ? 0x20 : 0x14; } static constexpr uint32_t getOffsetToProtocols(bool is64) { return is64 ? 0x28 : 0x18; } static constexpr uint32_t getOffsetToProperties(bool is64) { return is64 ? 0x40 : 0x24; } }; /*! * @class ObjCCategory * * @abstract * Class to encapsulate accessing (and one day building) objc categories */ struct VIS_HIDDEN ObjCCategory { // Note a category looks like this to libobjc: // template<typename PtrTy> // struct category_t { // PtrTy nameVMAddr; // PtrTy clsVMAddr; // PtrTy instanceMethodsVMAddr; // PtrTy classMethodsVMAddr; // PtrTy protocolsVMAddr; // PtrTy instancePropertiesVMAddr; // // Fields below this point are not always present on disk. // PtrTy classPropertiesVMAddr; // }; static constexpr uint32_t getOffsetToName(bool is64) { return 0; } static constexpr uint32_t getOffsetToClass(bool is64) { return is64 ? 0x08 : 0x04; } static constexpr uint32_t getOffsetToInstanceMethods(bool is64) { return is64 ? 0x10 : 0x08; } static constexpr uint32_t getOffsetToClassMethods(bool is64) { return is64 ? 0x18 : 0x0C; } static constexpr uint32_t getOffsetToProtocols(bool is64) { return is64 ? 0x20 : 0x10; } static constexpr uint32_t getOffsetToInstanceProperties(bool is64) { return is64 ? 0x28 : 0x14; } static constexpr uint32_t getOffsetToClassProperties(bool is64) { return is64 ? 0x30 : 0x18; } }; struct VIS_HIDDEN ObjCMethodList { // // Note a method list looks like this to libobjc: // { // uint32_t entsize; // uint32_t count; // uint8_t methodArrayBase[]; // Note this is the start the array method_t[0] // } // This matches the bits in the objc runtime enum : uint32_t { methodListIsUniqued = 0x1, methodListIsSorted = 0x2, methodListUsesSelectorOffsets = 0x40000000, methodListIsRelative = 0x80000000, // The size is bits 2 through 16 of the entsize field // The low 2 bits are uniqued/sorted as above. The upper 16-bits // are reserved for other flags methodListSizeMask = 0x0000FFFC }; // The method list stores the size of each element: // - pointer based method lists: 3 * uintptr_t // - relative method lists: 3 * uint32_t uint32_t getMethodSize() const; uint32_t getMethodCount() const; // Returns true if this is a relative method list. False if its pointer based bool usesRelativeOffsets() const; }; struct VIS_HIDDEN ObjCProtocolList { static constexpr uint32_t headerSize(bool is64) { return is64 ? 0x08 : 0x04; } uint32_t count(bool is64) const; // Note a protocol list looks like this to libobjc: // template<typename PtrTy> // struct protocol_list_t { // PtrTy count; // PtrTy list[]; // }; }; /*! * @class ObjCProtocol * * @abstract * Class to encapsulate accessing (and one day building) objc protocols */ struct VIS_HIDDEN ObjCProtocol { // Note a category looks like this to libobjc: // template<typename PtrTy> // struct protocol_t { // PtrTy isaVMAddr; // PtrTy nameVMAddr; // PtrTy protocolsVMAddr; // PtrTy instanceMethodsVMAddr; // PtrTy classMethodsVMAddr; // PtrTy optionalInstanceMethodsVMAddr; // PtrTy optionalClassMethodsVMAddr; // PtrTy instancePropertiesVMAddr; // uint32_t size; // uint32_t flags; // // Fields below this point are not always present on disk. // PtrTy extendedMethodTypesVMAddr; // PtrTy demangledNameVMAddr; // PtrTy classPropertiesVMAddr; // }; static constexpr uint32_t getOffsetToName(bool is64) { return is64 ? 0x8 : 0x4; } static constexpr uint32_t getOffsetToInstanceMethods(bool is64) { return is64 ? 0x18 : 0xC; } static constexpr uint32_t getOffsetToClassMethods(bool is64) { return is64 ? 0x20 : 0x10; } static constexpr uint32_t getOffsetToOptionalInstanceMethods(bool is64) { return is64 ? 0x28 : 0x14; } static constexpr uint32_t getOffsetToOptionalClassMethods(bool is64) { return is64 ? 0x30 : 0x18; } static constexpr uint32_t getOffsetToSize(bool is64) { return is64 ? 0x40 : 0x20; } }; struct VIS_HIDDEN ObjCPropertyList { // // Note a property list looks like this to libobjc: // { // uint32_t entsize; // uint32_t count; // uint8_t propertyArrayBase[]; // Note this is the start the array property_t[0] // } // The list stores the size of each element: uint32_t getPropertySize() const; uint32_t getPropertyCount() const; }; /*! * @class ObjCImageInfo * * @abstract * Class to encapsulate accessing (and one day building) objc image info */ struct VIS_HIDDEN ObjCImageInfo { // struct objc_image_info { // uint32_t version; // uint32_t flags; // }; // FIXME: Get all the other values and perhaps make these an enum static constexpr uint64_t OBJC_IMAGE_SIGNED_CLASS_RO = (1<<4); static constexpr uint64_t OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES = (1<<6); }; } // namespace mach_o #endif /* mach_o_ObjC_h */ |