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 316 317 318 319 320 321 322 323 324 325 326 327 328 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- * * Copyright (c) 2018 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_FIXUP_CHAINS__ #define __MACH_O_FIXUP_CHAINS__ 7 #include <stdint.h> //#define LC_DYLD_EXPORTS_TRIE 0x80000033 // used with linkedit_data_command //#define LC_DYLD_CHAINED_FIXUPS 0x80000034 // used with linkedit_data_command, payload is dyld_chained_fixups_header // header of the LC_DYLD_CHAINED_FIXUPS payload struct dyld_chained_fixups_header { uint32_t fixups_version; // 0 uint32_t starts_offset; // offset of dyld_chained_starts_in_image in chain_data uint32_t imports_offset; // offset of imports table in chain_data uint32_t symbols_offset; // offset of symbol strings in chain_data uint32_t imports_count; // number of imported symbol names uint32_t imports_format; // DYLD_CHAINED_IMPORT* uint32_t symbols_format; // 0 => uncompressed, 1 => zlib compressed }; // This struct is embedded in LC_DYLD_CHAINED_FIXUPS payload struct dyld_chained_starts_in_image { uint32_t seg_count; uint32_t seg_info_offset[1]; // each entry is offset into this struct for that segment // followed by pool of dyld_chain_starts_in_segment data }; // This struct is embedded in dyld_chain_starts_in_image // and passed down to the kernel for page-in linking struct dyld_chained_starts_in_segment { uint32_t size; // size of this (amount kernel needs to copy) uint16_t page_size; // 0x1000 or 0x4000 uint16_t pointer_format; // DYLD_CHAINED_PTR_* uint64_t segment_offset; // offset in memory to start of segment uint32_t max_valid_pointer; // for 32-bit OS, any value beyond this is not a pointer uint16_t page_count; // how many pages are in array uint16_t page_start[1]; // each entry is offset in each page of first element in chain // or DYLD_CHAINED_PTR_START_NONE if no fixups on page // uint16_t chain_starts[1]; // some 32-bit formats may require multiple starts per page. // for those, if high bit is set in page_starts[], then it // is index into chain_starts[] which is a list of starts // the last of which has the high bit set }; enum { DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups DYLD_CHAINED_PTR_START_MULTI = 0x8000, // used in page_start[] to denote a page which has multiple starts DYLD_CHAINED_PTR_START_LAST = 0x8000, // used in chain_starts[] to denote last start in list for page }; // This struct is embedded in __TEXT,__chain_starts section in firmware struct dyld_chained_starts_offsets { uint32_t pointer_format; // DYLD_CHAINED_PTR_32_FIRMWARE or DYLD_CHAINED_PTR_ARM64E_KERNEL uint32_t starts_count; // number of starts in array uint32_t chain_starts[1]; // array chain start offsets }; // values for dyld_chained_starts_in_segment.pointer_format enum { DYLD_CHAINED_PTR_ARM64E = 1, // stride 8, unauth target is vmaddr DYLD_CHAINED_PTR_64 = 2, // target is vmaddr DYLD_CHAINED_PTR_32 = 3, DYLD_CHAINED_PTR_32_CACHE = 4, DYLD_CHAINED_PTR_32_FIRMWARE = 5, DYLD_CHAINED_PTR_64_OFFSET = 6, // target is vm offset DYLD_CHAINED_PTR_ARM64E_OFFSET = 7, // old name DYLD_CHAINED_PTR_ARM64E_KERNEL = 7, // stride 4, unauth target is vm offset DYLD_CHAINED_PTR_64_KERNEL_CACHE = 8, DYLD_CHAINED_PTR_ARM64E_USERLAND = 9, // stride 8, unauth target is vm offset DYLD_CHAINED_PTR_ARM64E_FIRMWARE = 10, // stride 4, unauth target is vmaddr DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE = 11, // stride 1, x86_64 kernel caches DYLD_CHAINED_PTR_ARM64E_USERLAND24 = 12, // stride 8, unauth target is vm offset, 24-bit bind DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE = 13, // stride 8, regular/auth targets both vm offsets. Only A keys supported DYLD_CHAINED_PTR_ARM64E_SEGMENTED = 14, // stride 4, rebase offsets use segIndex and segOffset }; // DYLD_CHAINED_PTR_ARM64E struct dyld_chained_ptr_arm64e_rebase { uint64_t target : 43, high8 : 8, next : 11, // 4 or 8-byte stide bind : 1, // == 0 auth : 1; // == 0 }; // DYLD_CHAINED_PTR_ARM64E struct dyld_chained_ptr_arm64e_bind { uint64_t ordinal : 16, zero : 16, addend : 19, // +/-256K next : 11, // 4 or 8-byte stide bind : 1, // == 1 auth : 1; // == 0 }; // DYLD_CHAINED_PTR_ARM64E struct dyld_chained_ptr_arm64e_auth_rebase { uint64_t target : 32, // runtimeOffset diversity : 16, addrDiv : 1, key : 2, next : 11, // 4 or 8-byte stide bind : 1, // == 0 auth : 1; // == 1 }; // DYLD_CHAINED_PTR_ARM64E struct dyld_chained_ptr_arm64e_auth_bind { uint64_t ordinal : 16, zero : 16, diversity : 16, addrDiv : 1, key : 2, next : 11, // 4 or 8-byte stide bind : 1, // == 1 auth : 1; // == 1 }; // DYLD_CHAINED_PTR_64/DYLD_CHAINED_PTR_64_OFFSET struct dyld_chained_ptr_64_rebase { uint64_t target : 36, // 64GB max image size (DYLD_CHAINED_PTR_64 => vmAddr, DYLD_CHAINED_PTR_64_OFFSET => runtimeOffset) high8 : 8, // top 8 bits set to this (DYLD_CHAINED_PTR_64 => after slide added, DYLD_CHAINED_PTR_64_OFFSET => before slide added) reserved : 7, // all zeros next : 12, // 4-byte stride bind : 1; // == 0 }; // DYLD_CHAINED_PTR_ARM64E_USERLAND24 struct dyld_chained_ptr_arm64e_bind24 { uint64_t ordinal : 24, zero : 8, addend : 19, // +/-256K next : 11, // 8-byte stide bind : 1, // == 1 auth : 1; // == 0 }; // DYLD_CHAINED_PTR_ARM64E_USERLAND24 struct dyld_chained_ptr_arm64e_auth_bind24 { uint64_t ordinal : 24, zero : 8, diversity : 16, addrDiv : 1, key : 2, next : 11, // 8-byte stide bind : 1, // == 1 auth : 1; // == 1 }; // DYLD_CHAINED_PTR_ARM64E_SEGMENTED struct dyld_chained_ptr_arm64e_segmented_rebase { uint32_t targetSegOffset : 28, // offset in segment targetSegIndex : 4; // index into segment address table uint32_t padding : 19, next : 12, // 4-byte stide auth : 1; // == 0 }; // DYLD_CHAINED_PTR_ARM64E_SEGMENTED struct dyld_chained_ptr_arm64e_auth_segmented_rebase { uint32_t targetSegOffset : 28, // offset in segment targetSegIndex : 4; // index into segment address table uint32_t diversity : 16, addrDiv : 1, key : 2, next : 12, // 4-byte stide auth : 1; // == 1 }; // DYLD_CHAINED_PTR_64 struct dyld_chained_ptr_64_bind { uint64_t ordinal : 24, addend : 8, // 0 thru 255 reserved : 19, // all zeros next : 12, // 4-byte stride bind : 1; // == 1 }; // DYLD_CHAINED_PTR_64_KERNEL_CACHE, DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE struct dyld_chained_ptr_64_kernel_cache_rebase { uint64_t target : 30, // basePointers[cacheLevel] + target cacheLevel : 2, // what level of cache to bind to (indexes a mach_header array) diversity : 16, addrDiv : 1, key : 2, next : 12, // 1 or 4-byte stide isAuth : 1; // 0 -> not authenticated. 1 -> authenticated }; // DYLD_CHAINED_PTR_32 // Note: for DYLD_CHAINED_PTR_32 some non-pointer values are co-opted into the chain // as out of range rebases. If an entry in the chain is > max_valid_pointer, then it // is not a pointer. To restore the value, subtract off the bias, which is // (64MB+max_valid_pointer)/2. struct dyld_chained_ptr_32_rebase { uint32_t target : 26, // vmaddr, 64MB max image size next : 5, // 4-byte stride bind : 1; // == 0 }; // DYLD_CHAINED_PTR_32 struct dyld_chained_ptr_32_bind { uint32_t ordinal : 20, addend : 6, // 0 thru 63 next : 5, // 4-byte stride bind : 1; // == 1 }; // DYLD_CHAINED_PTR_32_CACHE struct dyld_chained_ptr_32_cache_rebase { uint32_t target : 30, // 1GB max dyld cache TEXT and DATA next : 2; // 4-byte stride }; // DYLD_CHAINED_PTR_32_FIRMWARE struct dyld_chained_ptr_32_firmware_rebase { uint32_t target : 26, // 64MB max firmware TEXT and DATA next : 6; // 4-byte stride }; // DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE struct dyld_chained_ptr_arm64e_shared_cache_rebase { uint64_t runtimeOffset : 34, // offset from the start of the shared cache high8 : 8, unused : 10, next : 11, // 8-byte stide auth : 1; // == 0 }; // DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE struct dyld_chained_ptr_arm64e_shared_cache_auth_rebase { uint64_t runtimeOffset : 34, // offset from the start of the shared cache diversity : 16, addrDiv : 1, keyIsData : 1, // implicitly always the 'A' key. 0 -> IA. 1 -> DA next : 11, // 8-byte stide auth : 1; // == 1 }; // values for dyld_chained_fixups_header.imports_format enum { DYLD_CHAINED_IMPORT = 1, DYLD_CHAINED_IMPORT_ADDEND = 2, DYLD_CHAINED_IMPORT_ADDEND64 = 3, }; // DYLD_CHAINED_IMPORT struct dyld_chained_import { uint32_t lib_ordinal : 8, // -15 .. 240 (0xF1 .. 0xF0) weak_import : 1, name_offset : 23; }; // DYLD_CHAINED_IMPORT_ADDEND struct dyld_chained_import_addend { uint32_t lib_ordinal : 8, // -15 .. 240 (0xF1 .. 0xF0) weak_import : 1, name_offset : 23; int32_t addend; }; // DYLD_CHAINED_IMPORT_ADDEND64 struct dyld_chained_import_addend64 { uint64_t lib_ordinal : 16, // -15 .. 65520 (0xFFF1 .. 0xFFF0) weak_import : 1, reserved : 15, name_offset : 32; uint64_t addend; }; #endif // __MACH_O_FIXUP_CHAINS__ |