1/* 2 * Copyright (c) 2007-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28#include <string.h> 29#include <mach/boolean.h> 30#include <sys/types.h> 31 32#if KERNEL 33 #include <libkern/libkern.h> 34 #include <mach/machine.h> 35#else 36 #include <stdlib.h> 37 #include <libkern/OSByteOrder.h> 38 39 /* Get machine.h from the kernel source so we can support all platforms 40 * that the kernel supports. Otherwise we're at the mercy of the host. 41 */ 42 #include "../../osfmk/mach/machine.h" 43#endif 44 45#define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld" 46#include <AssertMacros.h> 47 48#include "kxld_array.h" 49#include "kxld_demangle.h" 50#include "kxld_dict.h" 51#include "kxld_reloc.h" 52#include "kxld_sect.h" 53#include "kxld_seg.h" 54#include "kxld_sym.h" 55#include "kxld_symtab.h" 56#include "kxld_util.h" 57#include "kxld_vtable.h" 58 59#if KXLD_PIC_KEXTS 60/* This will try to pull in mach/machine.h, so it has to come after the 61 * explicit include above. 62 */ 63#include <mach-o/loader.h> 64#endif 65 66/* include target-specific relocation prototypes */ 67#include <mach-o/reloc.h> 68#if KXLD_USER_OR_X86_64 69#include <mach-o/x86_64/reloc.h> 70#endif 71#if KXLD_USER_OR_ARM 72#include <mach-o/arm/reloc.h> 73#endif 74 75#define KXLD_TARGET_NONE (u_int) 0x0 76#define KXLD_TARGET_VALUE (u_int) 0x1 77#define KXLD_TARGET_SECTNUM (u_int) 0x2 78#define KXLD_TARGET_SYMBOLNUM (u_int) 0x3 79#define KXLD_TARGET_LOOKUP (u_int) 0x4 80#define KXLD_TARGET_GOT (u_int) 0x5 81 82#define ABSOLUTE_VALUE(x) (((x) < 0) ? -(x) : (x)) 83 84#define LO16(x) (0x0000FFFF & x) 85#define LO16S(x) ((0x0000FFFF & x) << 16) 86#define HI16(x) (0xFFFF0000 & x) 87#define HI16S(x) ((0xFFFF0000 & x) >> 16) 88#define BIT15(x) (0x00008000 & x) 89#define BR14I(x) (0xFFFF0003 & x) 90#define BR14D(x) (0x0000FFFC & x) 91#define BR24I(x) (0xFC000003 & x) 92#define BR24D(x) (0x03FFFFFC & x) 93#define HADISP 0x00010000 94#define BR14_LIMIT 0x00008000 95#define BR24_LIMIT 0x02000000 96#define IS_COND_BR_INSTR(x) ((x & 0xFC000000) == 0x40000000) 97#define IS_NOT_ALWAYS_TAKEN(x) ((x & 0x03E00000) != 0x02800000) 98#define FLIP_PREDICT_BIT(x) x ^= 0x00200000 99 100#define SIGN_EXTEND_MASK(n) (1 << ((n) - 1)) 101#define SIGN_EXTEND(x,n) (((x) ^ SIGN_EXTEND_MASK(n)) - SIGN_EXTEND_MASK(n)) 102#define BR14_NBITS_DISPLACEMENT 16 103#define BR24_NBITS_DISPLACEMENT 26 104 105#define X86_64_RIP_RELATIVE_LIMIT 0x80000000UL 106 107/******************************************************************************* 108* Prototypes 109*******************************************************************************/ 110#if KXLD_USER_OR_I386 111static boolean_t generic_reloc_has_pair(u_int _type) 112 __attribute__((const)); 113static u_int generic_reloc_get_pair_type(u_int _prev_type) 114 __attribute__((const)); 115static boolean_t generic_reloc_has_got(u_int _type) 116 __attribute__((const)); 117static kern_return_t generic_process_reloc(const KXLDRelocator *relocator, 118 u_char *instruction, u_int length, u_int pcrel, kxld_addr_t base_pc, 119 kxld_addr_t link_pc, kxld_addr_t link_disp, u_int type, kxld_addr_t target, 120 kxld_addr_t pair_target, boolean_t swap); 121#endif /* KXLD_USER_OR_I386 */ 122 123#if KXLD_USER_OR_X86_64 124static boolean_t x86_64_reloc_has_pair(u_int _type) 125 __attribute__((const)); 126static u_int x86_64_reloc_get_pair_type(u_int _prev_type) 127 __attribute__((const)); 128static boolean_t x86_64_reloc_has_got(u_int _type) 129 __attribute__((const)); 130static kern_return_t x86_64_process_reloc(const KXLDRelocator *relocator, 131 u_char *instruction, u_int length, u_int pcrel, kxld_addr_t base_pc, 132 kxld_addr_t link_pc, kxld_addr_t link_disp, u_int type, kxld_addr_t target, 133 kxld_addr_t pair_target, boolean_t swap); 134static kern_return_t calculate_displacement_x86_64(uint64_t target, 135 uint64_t adjustment, int32_t *instr32); 136#endif /* KXLD_USER_OR_X86_64 */ 137 138#if KXLD_USER_OR_ARM 139static boolean_t arm_reloc_has_pair(u_int _type) 140 __attribute__((const)); 141static u_int arm_reloc_get_pair_type(u_int _prev_type) 142 __attribute__((const)); 143static boolean_t arm_reloc_has_got(u_int _type) 144 __attribute__((const)); 145static kern_return_t arm_process_reloc(const KXLDRelocator *relocator, 146 u_char *instruction, u_int length, u_int pcrel, kxld_addr_t base_pc, 147 kxld_addr_t link_pc, kxld_addr_t link_disp, u_int type, kxld_addr_t target, 148 kxld_addr_t pair_target, boolean_t swap); 149#endif /* KXLD_USER_OR_ARM */ 150 151#if KXLD_USER_OR_ILP32 152static kxld_addr_t get_pointer_at_addr_32(const KXLDRelocator *relocator, 153 const u_char *data, u_long offset) 154 __attribute__((pure, nonnull)); 155#endif /* KXLD_USER_OR_ILP32 */ 156#if KXLD_USER_OR_LP64 157static kxld_addr_t get_pointer_at_addr_64(const KXLDRelocator *relocator, 158 const u_char *data, u_long offset) 159 __attribute__((pure, nonnull)); 160#endif /* KXLD_USER_OR_LP64 */ 161 162static u_int count_relocatable_relocs(const KXLDRelocator *relocator, 163 const struct relocation_info *relocs, u_int nrelocs) 164 __attribute__((pure)); 165 166static kern_return_t calculate_targets(KXLDRelocator *relocator, 167 kxld_addr_t *_target, kxld_addr_t *_pair_target, const KXLDReloc *reloc); 168 169static kxld_addr_t align_raw_function_address(const KXLDRelocator *relocator, 170 kxld_addr_t value); 171 172static kern_return_t get_target_by_address_lookup(kxld_addr_t *target, 173 kxld_addr_t addr, const KXLDArray *sectarray); 174 175static kern_return_t check_for_direct_pure_virtual_call( 176 const KXLDRelocator *relocator, u_long offset); 177 178#if KXLD_PIC_KEXTS 179static u_long get_macho_data_size_for_array(const KXLDArray *relocs); 180 181static kern_return_t export_macho_for_array(const KXLDRelocator *relocator, 182 const KXLDArray *relocs, struct relocation_info **dstp); 183#endif /* KXLD_PIC_KEXTS */ 184 185/******************************************************************************* 186*******************************************************************************/ 187kern_return_t 188kxld_relocator_init(KXLDRelocator *relocator, u_char *file, 189 const KXLDSymtab *symtab, const KXLDArray *sectarray, cpu_type_t cputype, 190 cpu_subtype_t cpusubtype __unused, boolean_t swap) 191{ 192 kern_return_t rval = KERN_FAILURE; 193 194 check(relocator); 195 196 switch(cputype) { 197#if KXLD_USER_OR_I386 198 case CPU_TYPE_I386: 199 relocator->reloc_has_pair = generic_reloc_has_pair; 200 relocator->reloc_get_pair_type = generic_reloc_get_pair_type; 201 relocator->reloc_has_got = generic_reloc_has_got; 202 relocator->process_reloc = generic_process_reloc; 203 relocator->function_align = 0; 204 relocator->is_32_bit = TRUE; 205 relocator->may_scatter = TRUE; 206 break; 207#endif /* KXLD_USER_OR_I386 */ 208#if KXLD_USER_OR_X86_64 209 case CPU_TYPE_X86_64: 210 relocator->reloc_has_pair = x86_64_reloc_has_pair; 211 relocator->reloc_get_pair_type = x86_64_reloc_get_pair_type; 212 relocator->reloc_has_got = x86_64_reloc_has_got; 213 relocator->process_reloc = x86_64_process_reloc; 214 relocator->function_align = 0; 215 relocator->is_32_bit = FALSE; 216 relocator->may_scatter = FALSE; 217 break; 218#endif /* KXLD_USER_OR_X86_64 */ 219#if KXLD_USER_OR_ARM 220 case CPU_TYPE_ARM: 221 relocator->reloc_has_pair = arm_reloc_has_pair; 222 relocator->reloc_get_pair_type = arm_reloc_get_pair_type; 223 relocator->reloc_has_got = arm_reloc_has_got; 224 relocator->process_reloc = arm_process_reloc; 225 relocator->function_align = 1; 226 relocator->is_32_bit = TRUE; 227 relocator->may_scatter = FALSE; 228 break; 229#endif /* KXLD_USER_OR_ARM */ 230 231 default: 232 rval = KERN_FAILURE; 233 kxld_log(kKxldLogLinking, kKxldLogErr, 234 kKxldLogArchNotSupported, cputype); 235 goto finish; 236 } 237 238 relocator->file = file; 239 relocator->symtab = symtab; 240 relocator->sectarray = sectarray; 241 relocator->is_32_bit = kxld_is_32_bit(cputype); 242 relocator->swap = swap; 243 244 rval = KERN_SUCCESS; 245 246finish: 247 return rval; 248} 249 250/******************************************************************************* 251*******************************************************************************/ 252kern_return_t 253kxld_reloc_create_macho(KXLDArray *relocarray, const KXLDRelocator *relocator, 254 const struct relocation_info *srcs, u_int nsrcs) 255{ 256 kern_return_t rval = KERN_FAILURE; 257 KXLDReloc *reloc = NULL; 258 u_int nrelocs = 0; 259 const struct relocation_info *src = NULL; 260 const struct scattered_relocation_info *scatsrc = NULL; 261 u_int i = 0; 262 u_int reloc_index = 0; 263 264 check(relocarray); 265 check(srcs); 266 267 /* If there are no relocation entries, just return */ 268 if (!nsrcs) { 269 rval = KERN_SUCCESS; 270 goto finish; 271 } 272 273 /* Count the number of non-pair relocs */ 274 nrelocs = count_relocatable_relocs(relocator, srcs, nsrcs); 275 276 if (nrelocs) { 277 278 /* Allocate the array of relocation entries */ 279 280 rval = kxld_array_init(relocarray, sizeof(KXLDReloc), nrelocs); 281 require_noerr(rval, finish); 282 283 /* Initialize the relocation entries */ 284 285 for (i = 0; i < nsrcs; ++i) { 286 src = srcs + i; 287 scatsrc = (const struct scattered_relocation_info *) src; 288 289 /* A section-based relocation entry can be skipped for absolute 290 * symbols. 291 */ 292 293 if (!(relocator->may_scatter && (src->r_address & R_SCATTERED)) && 294 !(src->r_extern) && (R_ABS == src->r_symbolnum)) 295 { 296 continue; 297 } 298 299 /* Pull out the data from the relocation entries. The target_type 300 * depends on the r_extern bit: 301 * Scattered -> Section Lookup by Address 302 * Local (not extern) -> Section by Index 303 * Extern -> Symbolnum by Index 304 */ 305 reloc = kxld_array_get_item(relocarray, reloc_index++); 306 if (relocator->may_scatter && (src->r_address & R_SCATTERED)) { 307 reloc->address = scatsrc->r_address; 308 reloc->pcrel = scatsrc->r_pcrel; 309 reloc->length = scatsrc->r_length; 310 reloc->reloc_type = scatsrc->r_type; 311 reloc->target = scatsrc->r_value; 312 reloc->target_type = KXLD_TARGET_LOOKUP; 313 } else { 314 reloc->address = src->r_address; 315 reloc->pcrel = src->r_pcrel; 316 reloc->length = src->r_length; 317 reloc->reloc_type = src->r_type; 318 reloc->target = src->r_symbolnum; 319 320 if (0 == src->r_extern) { 321 reloc->target_type = KXLD_TARGET_SECTNUM; 322 reloc->target -= 1; 323 } else { 324 reloc->target_type = KXLD_TARGET_SYMBOLNUM; 325 } 326 } 327 328 /* Find the pair entry if it exists */ 329 330 if (relocator->reloc_has_pair(reloc->reloc_type)) { 331 ++i; 332 require_action(i < nsrcs, finish, rval=KERN_FAILURE); 333 334 src = srcs + i; 335 scatsrc = (const struct scattered_relocation_info *) src; 336 337 if (relocator->may_scatter && (src->r_address & R_SCATTERED)) { 338 require_action(relocator->reloc_get_pair_type( 339 reloc->reloc_type) == scatsrc->r_type, 340 finish, rval=KERN_FAILURE); 341 reloc->pair_address= scatsrc->r_address; 342 reloc->pair_target = scatsrc->r_value; 343 reloc->pair_target_type = KXLD_TARGET_LOOKUP; 344 } else { 345 require_action(relocator->reloc_get_pair_type( 346 reloc->reloc_type) == scatsrc->r_type, 347 finish, rval=KERN_FAILURE); 348 reloc->pair_address = scatsrc->r_address; 349 if (src->r_extern) { 350 reloc->pair_target = src->r_symbolnum; 351 reloc->pair_target_type = KXLD_TARGET_SYMBOLNUM; 352 } else { 353 reloc->pair_target = src->r_address; 354 reloc->pair_target_type = KXLD_TARGET_VALUE; 355 } 356 } 357 } else { 358 reloc->pair_target = 0; 359 if (relocator->reloc_has_got(reloc->reloc_type)) { 360 reloc->pair_target_type = KXLD_TARGET_GOT; 361 } else { 362 reloc->pair_target_type = KXLD_TARGET_NONE; 363 } 364 } 365 } 366 } 367 368 rval = KERN_SUCCESS; 369 370finish: 371 return rval; 372} 373 374 375/******************************************************************************* 376* Relocatable relocs : 377* 1) Are not _PAIR_ relocs 378* 2) Don't reference N_ABS symbols 379*******************************************************************************/ 380static u_int 381count_relocatable_relocs(const KXLDRelocator *relocator, 382 const struct relocation_info *relocs, u_int nrelocs) 383{ 384 u_int num_nonpair_relocs = 0; 385 u_int i = 0; 386 const struct relocation_info *reloc = NULL; 387 const struct scattered_relocation_info *sreloc = NULL; 388 389 check(relocator); 390 check(relocs); 391 392 /* Loop over all of the relocation entries */ 393 394 num_nonpair_relocs = 1; 395 for (i = 1; i < nrelocs; ++i) { 396 reloc = relocs + i; 397 398 if (reloc->r_address & R_SCATTERED) { 399 /* A scattered relocation entry is relocatable as long as it's not a 400 * pair. 401 */ 402 sreloc = (const struct scattered_relocation_info *) reloc; 403 404 num_nonpair_relocs += 405 !relocator->reloc_has_pair(sreloc->r_type); 406 } else { 407 /* A normal relocation entry is relocatable if it is not a pair and 408 * if it is not a section-based relocation for an absolute symbol. 409 */ 410 num_nonpair_relocs += 411 !(relocator->reloc_has_pair(reloc->r_type) 412 || (0 == reloc->r_extern && R_ABS == reloc->r_symbolnum)); 413 } 414 415 } 416 417 return num_nonpair_relocs; 418} 419 420/******************************************************************************* 421*******************************************************************************/ 422void 423kxld_relocator_clear(KXLDRelocator *relocator) 424{ 425 bzero(relocator, sizeof(*relocator)); 426} 427 428/******************************************************************************* 429*******************************************************************************/ 430boolean_t 431kxld_relocator_has_pair(const KXLDRelocator *relocator, u_int r_type) 432{ 433 check(relocator); 434 435 return relocator->reloc_has_pair(r_type); 436} 437 438/******************************************************************************* 439*******************************************************************************/ 440u_int 441kxld_relocator_get_pair_type(const KXLDRelocator *relocator, 442 u_int prev_r_type) 443{ 444 check(relocator); 445 446 return relocator->reloc_get_pair_type(prev_r_type); 447} 448 449/******************************************************************************* 450*******************************************************************************/ 451boolean_t 452kxld_relocator_has_got(const KXLDRelocator *relocator, u_int r_type) 453{ 454 check(relocator); 455 456 return relocator->reloc_has_got(r_type); 457} 458 459/******************************************************************************* 460*******************************************************************************/ 461KXLDSym * 462kxld_reloc_get_symbol(const KXLDRelocator *relocator, const KXLDReloc *reloc, 463 const u_char *data) 464{ 465 KXLDSym *sym = NULL; 466 kxld_addr_t value = 0; 467 468 check(reloc); 469 470 switch (reloc->target_type) { 471 case KXLD_TARGET_SYMBOLNUM: 472 sym = kxld_symtab_get_symbol_by_index(relocator->symtab, reloc->target); 473 break; 474 case KXLD_TARGET_SECTNUM: 475 if (data) { 476 value = kxld_relocator_get_pointer_at_addr(relocator, data, 477 reloc->address); 478 sym = kxld_symtab_get_cxx_symbol_by_value(relocator->symtab, value); 479 } 480 break; 481 default: 482 sym = NULL; 483 break; 484 } 485 486 return sym; 487} 488 489/******************************************************************************* 490*******************************************************************************/ 491kern_return_t 492kxld_reloc_get_reloc_index_by_offset(const KXLDArray *relocs, 493 kxld_size_t offset, u_int *idx) 494{ 495 kern_return_t rval = KERN_FAILURE; 496 KXLDReloc *reloc = NULL; 497 u_int i = 0; 498 499 for (i = 0; i < relocs->nitems; ++i) { 500 reloc = kxld_array_get_item(relocs, i); 501 if (reloc->address == offset) break; 502 } 503 504 if (i >= relocs->nitems) { 505 rval = KERN_FAILURE; 506 goto finish; 507 } 508 509 *idx = i; 510 rval = KERN_SUCCESS; 511 512finish: 513 return rval; 514} 515 516/******************************************************************************* 517*******************************************************************************/ 518KXLDReloc * 519kxld_reloc_get_reloc_by_offset(const KXLDArray *relocs, kxld_addr_t offset) 520{ 521 kern_return_t rval = KERN_FAILURE; 522 KXLDReloc *reloc = NULL; 523 u_int i = 0; 524 525 rval = kxld_reloc_get_reloc_index_by_offset(relocs, offset, &i); 526 if (rval) goto finish; 527 528 reloc = kxld_array_get_item(relocs, i); 529 530finish: 531 return reloc; 532} 533 534#if KXLD_PIC_KEXTS 535/******************************************************************************* 536*******************************************************************************/ 537u_long 538kxld_reloc_get_macho_header_size() 539{ 540 return sizeof(struct dysymtab_command); 541} 542 543/******************************************************************************* 544*******************************************************************************/ 545u_long 546kxld_reloc_get_macho_data_size(const KXLDArray *locrelocs, 547 const KXLDArray *extrelocs) 548{ 549 u_long rval = 0; 550 551 rval += get_macho_data_size_for_array(locrelocs); 552 rval += get_macho_data_size_for_array(extrelocs); 553 554 return (rval); 555} 556 557/******************************************************************************* 558*******************************************************************************/ 559kern_return_t 560kxld_reloc_export_macho(const KXLDRelocator *relocator, 561 const KXLDArray *locrelocs, const KXLDArray *extrelocs, 562 u_char *buf, u_long *header_offset, u_long header_size, 563 u_long *data_offset, u_long size) 564{ 565 kern_return_t rval = KERN_FAILURE; 566 struct dysymtab_command *dysymtabhdr = NULL; 567 struct relocation_info *start = NULL; 568 struct relocation_info *dst = NULL; 569 u_long count = 0; 570 u_long data_size = 0; 571 572 check(locrelocs); 573 check(extrelocs); 574 check(buf); 575 check(header_offset); 576 check(data_offset); 577 578 require_action(sizeof(*dysymtabhdr) <= header_size - *header_offset, finish, rval=KERN_FAILURE); 579 dysymtabhdr = (struct dysymtab_command *) ((void *) (buf + *header_offset)); 580 *header_offset += sizeof(*dysymtabhdr); 581 582 data_size = kxld_reloc_get_macho_data_size(locrelocs, extrelocs); 583 require_action((*data_offset + data_size) <= size, finish, rval=KERN_FAILURE); 584 585 start = dst = (struct relocation_info *) ((void *) (buf + *data_offset)); 586 587 rval = export_macho_for_array(relocator, locrelocs, &dst); 588 require_noerr(rval, finish); 589 590 rval = export_macho_for_array(relocator, extrelocs, &dst); 591 require_noerr(rval, finish); 592 593 count = dst - start; 594 595 memset(dysymtabhdr, 0, sizeof(*dysymtabhdr)); 596 dysymtabhdr->cmd = LC_DYSYMTAB; 597 dysymtabhdr->cmdsize = (uint32_t) sizeof(*dysymtabhdr); 598 dysymtabhdr->locreloff = (uint32_t) *data_offset; 599 dysymtabhdr->nlocrel = (uint32_t) count; 600 601 *data_offset += count * sizeof(struct relocation_info); 602 603 rval = KERN_SUCCESS; 604finish: 605 return rval; 606} 607#endif /* KXLD_PIC_KEXTS */ 608 609/******************************************************************************* 610*******************************************************************************/ 611kxld_addr_t 612kxld_relocator_get_pointer_at_addr(const KXLDRelocator *relocator, 613 const u_char *data, u_long offset) 614{ 615 kxld_addr_t value; 616 617 KXLD_3264_FUNC(relocator->is_32_bit, value, 618 get_pointer_at_addr_32, get_pointer_at_addr_64, 619 relocator, data, offset); 620 621 return value; 622} 623 624#if KXLD_USER_OR_ILP32 625/******************************************************************************* 626*******************************************************************************/ 627static kxld_addr_t 628get_pointer_at_addr_32(const KXLDRelocator *relocator, 629 const u_char *data, u_long offset) 630{ 631 uint32_t addr = 0; 632 633 check(relocator); 634 635 addr = *(const uint32_t *) ((void *) (data + offset)); 636#if !KERNEL 637 if (relocator->swap) { 638 addr = OSSwapInt32(addr); 639 } 640#endif 641 642 return align_raw_function_address(relocator, addr); 643} 644#endif /* KXLD_USER_OR_ILP32 */ 645 646#if KXLD_USER_OR_LP64 647/******************************************************************************* 648*******************************************************************************/ 649static kxld_addr_t 650get_pointer_at_addr_64(const KXLDRelocator *relocator, 651 const u_char *data, u_long offset) 652{ 653 uint64_t addr = 0; 654 655 check(relocator); 656 657 addr = *(const uint64_t *) ((void *) (data + offset)); 658#if !KERNEL 659 if (relocator->swap) { 660 addr = OSSwapInt64(addr); 661 } 662#endif 663 664 return align_raw_function_address(relocator, addr); 665} 666#endif /* KXLD_USER_OR_LP64 */ 667 668/******************************************************************************* 669*******************************************************************************/ 670void 671kxld_relocator_set_vtables(KXLDRelocator *relocator, const KXLDDict *vtables) 672{ 673 relocator->vtables = vtables; 674} 675 676/******************************************************************************* 677* When we're inspecting the raw binary and not the symbol table, value may 678* hold a THUMB address (with bit 0 set to 1) but the index will have the real 679* address (bit 0 set to 0). So if bit 0 is set here, we clear it. This only 680* impacts ARM for now, but it's implemented as a generic function alignment 681* mask. 682*******************************************************************************/ 683static kxld_addr_t 684align_raw_function_address(const KXLDRelocator *relocator, kxld_addr_t value) 685{ 686 if (relocator->function_align) { 687 value &= ~((1ULL << relocator->function_align) - 1); 688 } 689 690 return value; 691} 692 693/******************************************************************************* 694*******************************************************************************/ 695kern_return_t 696kxld_relocator_process_sect_reloc(KXLDRelocator *relocator, 697 const KXLDReloc *reloc, const KXLDSect *sect) 698{ 699 kern_return_t rval = KERN_FAILURE; 700 u_char *instruction = NULL; 701 kxld_addr_t target = 0; 702 kxld_addr_t pair_target = 0; 703 kxld_addr_t base_pc = 0; 704 kxld_addr_t link_pc = 0; 705 kxld_addr_t link_disp = 0; 706 707 check(relocator); 708 check(reloc); 709 check(sect); 710 711 /* Find the instruction */ 712 713 instruction = sect->data + reloc->address; 714 715 /* Calculate the target */ 716 717 rval = calculate_targets(relocator, &target, &pair_target, reloc); 718 require_noerr(rval, finish); 719 720 base_pc = reloc->address; 721 link_pc = base_pc + sect->link_addr; 722 link_disp = sect->link_addr - sect->base_addr; 723 724 /* Relocate */ 725 726 rval = relocator->process_reloc(relocator, instruction, reloc->length, 727 reloc->pcrel, base_pc, link_pc, link_disp, reloc->reloc_type, target, 728 pair_target, relocator->swap); 729 require_noerr(rval, finish); 730 731 /* Return */ 732 733 relocator->current_vtable = NULL; 734 rval = KERN_SUCCESS; 735 736finish: 737 return rval; 738} 739 740/******************************************************************************* 741*******************************************************************************/ 742kern_return_t 743kxld_reloc_update_symindex(KXLDReloc *reloc, u_int symindex) 744{ 745 kern_return_t rval = KERN_FAILURE; 746 747 require_action(reloc->target_type == KXLD_TARGET_SYMBOLNUM, 748 finish, rval = KERN_FAILURE); 749 750 reloc->target = symindex; 751 752 rval = KERN_SUCCESS; 753 754finish: 755 return rval; 756} 757 758/******************************************************************************* 759*******************************************************************************/ 760kern_return_t 761kxld_relocator_process_table_reloc(KXLDRelocator *relocator, 762 const KXLDReloc *reloc, const KXLDSeg *seg, kxld_addr_t link_addr) 763{ 764 kern_return_t rval = KERN_FAILURE; 765 u_char *instruction = NULL; 766 kxld_addr_t target = 0; 767 kxld_addr_t pair_target = 0; 768 kxld_addr_t base_pc = 0; 769 kxld_addr_t link_pc = 0; 770 u_long offset = 0; 771 772 check(relocator); 773 check(reloc); 774 775 /* Find the instruction */ 776 777 offset = (u_long)(seg->fileoff + (reloc->address - seg->base_addr)); 778 instruction = relocator->file + offset; 779 780 /* Calculate the target */ 781 782 rval = calculate_targets(relocator, &target, &pair_target, reloc); 783 require_noerr(rval, finish); 784 785 base_pc = reloc->address; 786 link_pc = base_pc + link_addr; 787 788 /* Relocate */ 789 790 rval = relocator->process_reloc(relocator, instruction, reloc->length, 791 reloc->pcrel, base_pc, link_pc, link_addr, reloc->reloc_type, target, 792 pair_target, relocator->swap); 793 require_noerr(rval, finish); 794 795 /* Return */ 796 797 relocator->current_vtable = NULL; 798 rval = KERN_SUCCESS; 799 800finish: 801 return rval; 802} 803 804/******************************************************************************* 805*******************************************************************************/ 806static kern_return_t 807calculate_targets(KXLDRelocator *relocator, kxld_addr_t *_target, 808 kxld_addr_t *_pair_target, const KXLDReloc *reloc) 809{ 810 kern_return_t rval = KERN_FAILURE; 811 const KXLDSect *sect = NULL; 812 const KXLDSym *sym = NULL; 813 kxld_addr_t target = 0; 814 kxld_addr_t pair_target = 0; 815 char *demangled_name = NULL; 816 size_t demangled_length = 0; 817 818 check(_target); 819 check(_pair_target); 820 *_target = 0; 821 *_pair_target = 0; 822 823 /* Find the target based on the lookup type */ 824 825 switch(reloc->target_type) { 826 case KXLD_TARGET_LOOKUP: 827 require_action(reloc->pair_target_type == KXLD_TARGET_NONE || 828 reloc->pair_target_type == KXLD_TARGET_LOOKUP || 829 reloc->pair_target_type == KXLD_TARGET_VALUE, 830 finish, rval=KERN_FAILURE); 831 832 rval = get_target_by_address_lookup(&target, reloc->target, 833 relocator->sectarray); 834 require_noerr(rval, finish); 835 836 if (reloc->pair_target_type == KXLD_TARGET_LOOKUP) { 837 rval = get_target_by_address_lookup(&pair_target, 838 reloc->pair_target, relocator->sectarray); 839 require_noerr(rval, finish); 840 } else if (reloc->pair_target_type == KXLD_TARGET_VALUE) { 841 pair_target = reloc->pair_target; 842 } 843 break; 844 case KXLD_TARGET_SECTNUM: 845 require_action(reloc->pair_target_type == KXLD_TARGET_NONE || 846 reloc->pair_target_type == KXLD_TARGET_VALUE, 847 finish, rval=KERN_FAILURE); 848 849 /* Get the target's section by section number */ 850 sect = kxld_array_get_item(relocator->sectarray, reloc->target); 851 require_action(sect, finish, rval=KERN_FAILURE); 852 853 /* target is the change in the section's address */ 854 target = sect->link_addr - sect->base_addr; 855 856 if (reloc->pair_target_type) { 857 pair_target = reloc->pair_target; 858 } else { 859 /* x86_64 needs to know when we have a non-external relocation, 860 * so we hack that information in here. 861 */ 862 pair_target = TRUE; 863 } 864 break; 865 case KXLD_TARGET_SYMBOLNUM: 866 require_action(reloc->pair_target_type == KXLD_TARGET_NONE || 867 reloc->pair_target_type == KXLD_TARGET_GOT || 868 reloc->pair_target_type == KXLD_TARGET_SYMBOLNUM || 869 reloc->pair_target_type == KXLD_TARGET_VALUE, finish, 870 rval=KERN_FAILURE); 871 872 /* Get the target's symbol by symbol number */ 873 sym = kxld_symtab_get_symbol_by_index(relocator->symtab, reloc->target); 874 require_action(sym, finish, rval=KERN_FAILURE); 875 876 /* If this symbol is a padslot that has already been replaced, then the 877 * only way a relocation entry can still reference it is if there is a 878 * vtable that has not been patched. The vtable patcher uses the 879 * MetaClass structure to find classes for patching, so an unpatched 880 * vtable means that there is an OSObject-dervied class that is missing 881 * its OSDeclare/OSDefine macros. 882 */ 883 require_action(!kxld_sym_is_padslot(sym) || !kxld_sym_is_replaced(sym), 884 finish, rval=KERN_FAILURE; 885 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogRelocatingPatchedSym, 886 kxld_demangle(sym->name, &demangled_name, &demangled_length))); 887 888 target = sym->link_addr; 889 890 if (kxld_sym_is_vtable(sym)) { 891 relocator->current_vtable = kxld_dict_find(relocator->vtables, sym->name); 892 } 893 894 /* Some relocation types need the GOT entry address instead of the 895 * symbol's actual address. These types don't have pair relocation 896 * entries, so we store the GOT entry address as the pair target. 897 */ 898 if (reloc->pair_target_type == KXLD_TARGET_VALUE) { 899 pair_target = reloc->pair_target; 900 } else if (reloc->pair_target_type == KXLD_TARGET_SYMBOLNUM ) { 901 sym = kxld_symtab_get_symbol_by_index(relocator->symtab, 902 reloc->pair_target); 903 require_action(sym, finish, rval=KERN_FAILURE); 904 pair_target = sym->link_addr; 905 } else if (reloc->pair_target_type == KXLD_TARGET_GOT) { 906 pair_target = sym->got_addr; 907 } 908 break; 909 default: 910 rval = KERN_FAILURE; 911 goto finish; 912 } 913 914 *_target = target; 915 *_pair_target = pair_target; 916 rval = KERN_SUCCESS; 917 918finish: 919 if (demangled_name) kxld_free(demangled_name, demangled_length); 920 return rval; 921} 922 923/******************************************************************************* 924*******************************************************************************/ 925static kern_return_t 926get_target_by_address_lookup(kxld_addr_t *target, kxld_addr_t addr, 927 const KXLDArray *sectarray) 928{ 929 kern_return_t rval = KERN_FAILURE; 930 const KXLDSect *sect = NULL; 931 kxld_addr_t start = 0; 932 kxld_addr_t end = 0; 933 u_int i = 0; 934 935 check(target); 936 check(sectarray); 937 *target = 0; 938 939 for (i = 0; i < sectarray->nitems; ++i) { 940 sect = kxld_array_get_item(sectarray, i); 941 start = sect->base_addr; 942 end = start + sect->size; 943 944 if (start <= addr && addr < end) break; 945 946 sect = NULL; 947 } 948 require_action(sect, finish, rval=KERN_FAILURE); 949 950 *target = sect->link_addr - sect->base_addr; 951 rval = KERN_SUCCESS; 952 953finish: 954 return rval; 955} 956 957/******************************************************************************* 958*******************************************************************************/ 959static kern_return_t 960check_for_direct_pure_virtual_call(const KXLDRelocator *relocator, u_long offset) 961{ 962 kern_return_t rval = KERN_FAILURE; 963 const KXLDVTableEntry *entry = NULL; 964 965 if (relocator->current_vtable) { 966 entry = kxld_vtable_get_entry_for_offset(relocator->current_vtable, 967 offset, relocator->is_32_bit); 968 require_action(!entry || !entry->patched.name || 969 !kxld_sym_name_is_pure_virtual(entry->patched.name), 970 finish, rval=KERN_FAILURE; 971 kxld_log(kKxldLogLinking, kKxldLogErr, 972 kKxldLogDirectPureVirtualCall)); 973 } 974 975 rval = KERN_SUCCESS; 976finish: 977 return rval; 978} 979 980#if KXLD_PIC_KEXTS 981/******************************************************************************* 982*******************************************************************************/ 983static u_long 984get_macho_data_size_for_array(const KXLDArray *relocs) 985{ 986 const KXLDReloc *reloc = NULL; 987 u_int i = 0; 988 u_long size = 0; 989 990 check(relocs); 991 992 for (i = 0; i < relocs->nitems; ++i) { 993 reloc = kxld_array_get_item(relocs, i); 994 if (!reloc->pcrel) { 995 size += sizeof(struct relocation_info); 996 if(reloc->pair_target_type != KXLD_TARGET_NONE) { 997 size += sizeof(struct relocation_info); 998 } 999 } 1000 } 1001 1002 return size; 1003} 1004 1005/******************************************************************************* 1006*******************************************************************************/ 1007static kern_return_t 1008export_macho_for_array(const KXLDRelocator *relocator, 1009 const KXLDArray *relocs, struct relocation_info **dstp) 1010{ 1011 kern_return_t rval = KERN_FAILURE; 1012 const KXLDReloc *reloc = NULL; 1013 struct relocation_info *dst = NULL; 1014 struct scattered_relocation_info *scatdst = NULL; 1015 u_int i = 0; 1016 1017 dst = *dstp; 1018 1019 for (i = 0; i < relocs->nitems; ++i) { 1020 reloc = kxld_array_get_item(relocs, i); 1021 scatdst = (struct scattered_relocation_info *) dst; 1022 1023 if (reloc->pcrel) { 1024 continue; 1025 } 1026 1027 switch (reloc->target_type) { 1028 case KXLD_TARGET_LOOKUP: 1029 scatdst->r_address = reloc->address; 1030 scatdst->r_pcrel = reloc->pcrel; 1031 scatdst->r_length = reloc->length; 1032 scatdst->r_type = reloc->reloc_type; 1033 scatdst->r_value = reloc->target; 1034 scatdst->r_scattered = 1; 1035 break; 1036 case KXLD_TARGET_SECTNUM: 1037 dst->r_address = reloc->address; 1038 dst->r_pcrel = reloc->pcrel; 1039 dst->r_length = reloc->length; 1040 dst->r_type = reloc->reloc_type; 1041 dst->r_symbolnum = reloc->target + 1; 1042 dst->r_extern = 0; 1043 break; 1044 case KXLD_TARGET_SYMBOLNUM: 1045 /* Assume that everything will be slid together; otherwise, 1046 * there is no sensible value for the section number. 1047 */ 1048 dst->r_address = reloc->address; 1049 dst->r_pcrel = reloc->pcrel; 1050 dst->r_length = reloc->length; 1051 dst->r_type = reloc->reloc_type; 1052 dst->r_symbolnum = 1; 1053 dst->r_extern = 0; 1054 break; 1055 default: 1056 rval = KERN_FAILURE; 1057 goto finish; 1058 } 1059 1060 ++dst; 1061 1062 if(reloc->pair_target_type != KXLD_TARGET_NONE) { 1063 ++i; 1064 require_action(i < relocs->nitems, finish, rval=KERN_FAILURE); 1065 scatdst = (struct scattered_relocation_info *) dst; 1066 switch (reloc->pair_target_type) { 1067 case KXLD_TARGET_LOOKUP: 1068 scatdst->r_address = reloc->pair_address; 1069 scatdst->r_pcrel = reloc->pcrel; 1070 scatdst->r_length = reloc->length; 1071 scatdst->r_type = relocator->reloc_get_pair_type(reloc->reloc_type); 1072 scatdst->r_value = reloc->pair_target; 1073 scatdst->r_scattered = 1; 1074 break; 1075 case KXLD_TARGET_SECTNUM: 1076 dst->r_address = reloc->pair_address; 1077 dst->r_pcrel = reloc->pcrel; 1078 dst->r_length = reloc->length; 1079 dst->r_type = relocator->reloc_get_pair_type(reloc->reloc_type); 1080 dst->r_symbolnum = reloc->pair_target + 1; 1081 dst->r_extern = 0; 1082 break; 1083 case KXLD_TARGET_SYMBOLNUM: 1084 dst->r_address = reloc->pair_address; 1085 dst->r_pcrel = reloc->pcrel; 1086 dst->r_length = reloc->length; 1087 dst->r_type = relocator->reloc_get_pair_type(reloc->reloc_type); 1088 dst->r_symbolnum = 1; 1089 dst->r_extern = 0; 1090 break; 1091 default: 1092 rval = KERN_FAILURE; 1093 goto finish; 1094 } 1095 ++dst; 1096 } 1097 } 1098 1099 rval = KERN_SUCCESS; 1100finish: 1101 *dstp = dst; 1102 return rval; 1103} 1104#endif /* KXLD_PIC_KEXTS */ 1105 1106#if KXLD_USER_OR_I386 1107/******************************************************************************* 1108*******************************************************************************/ 1109static boolean_t 1110generic_reloc_has_pair(u_int _type) 1111{ 1112 enum reloc_type_generic type = _type; 1113 1114 return (type == GENERIC_RELOC_SECTDIFF || 1115 type == GENERIC_RELOC_LOCAL_SECTDIFF); 1116} 1117 1118/******************************************************************************* 1119*******************************************************************************/ 1120static u_int 1121generic_reloc_get_pair_type(u_int _prev_type __unused) 1122{ 1123 return GENERIC_RELOC_PAIR; 1124} 1125 1126/******************************************************************************* 1127*******************************************************************************/ 1128static boolean_t generic_reloc_has_got(u_int _type __unused) 1129{ 1130 return FALSE; 1131} 1132 1133/******************************************************************************* 1134*******************************************************************************/ 1135static kern_return_t 1136generic_process_reloc(const KXLDRelocator *relocator, u_char *instruction, 1137 u_int length, u_int pcrel, kxld_addr_t _base_pc, kxld_addr_t _link_pc, 1138 kxld_addr_t _link_disp __unused, u_int _type, kxld_addr_t _target, 1139 kxld_addr_t _pair_target, boolean_t swap __unused) 1140{ 1141 kern_return_t rval = KERN_FAILURE; 1142 uint32_t base_pc = (uint32_t) _base_pc; 1143 uint32_t link_pc = (uint32_t) _link_pc; 1144 uint32_t *instr_addr = NULL; 1145 uint32_t instr_data = 0; 1146 uint32_t target = (uint32_t) _target; 1147 uint32_t pair_target = (uint32_t) _pair_target; 1148 enum reloc_type_generic type = _type; 1149 1150 check(instruction); 1151 require_action(length == 2, finish, rval=KERN_FAILURE); 1152 1153 if (pcrel) target = target + base_pc - link_pc; 1154 1155 instr_addr = (uint32_t *) ((void *) instruction); 1156 instr_data = *instr_addr; 1157 1158#if !KERNEL 1159 if (swap) instr_data = OSSwapInt32(instr_data); 1160#endif 1161 1162 rval = check_for_direct_pure_virtual_call(relocator, instr_data); 1163 require_noerr(rval, finish); 1164 1165 switch (type) { 1166 case GENERIC_RELOC_VANILLA: 1167 instr_data += target; 1168 break; 1169 case GENERIC_RELOC_SECTDIFF: 1170 case GENERIC_RELOC_LOCAL_SECTDIFF: 1171 instr_data = instr_data + target - pair_target; 1172 break; 1173 case GENERIC_RELOC_PB_LA_PTR: 1174 rval = KERN_FAILURE; 1175 goto finish; 1176 case GENERIC_RELOC_PAIR: 1177 default: 1178 rval = KERN_FAILURE; 1179 goto finish; 1180 } 1181 1182#if !KERNEL 1183 if (swap) instr_data = OSSwapInt32(instr_data); 1184#endif 1185 1186 *instr_addr = instr_data; 1187 1188 rval = KERN_SUCCESS; 1189 1190finish: 1191 return rval; 1192} 1193#endif /* KXLD_USER_OR_I386 */ 1194 1195#if KXLD_USER_OR_X86_64 1196/******************************************************************************* 1197*******************************************************************************/ 1198static boolean_t 1199x86_64_reloc_has_pair(u_int _type) 1200{ 1201 enum reloc_type_x86_64 type = _type; 1202 1203 return (type == X86_64_RELOC_SUBTRACTOR); 1204} 1205 1206/******************************************************************************* 1207*******************************************************************************/ 1208static u_int 1209x86_64_reloc_get_pair_type(u_int _prev_type __unused) 1210{ 1211 return X86_64_RELOC_UNSIGNED; 1212} 1213 1214/******************************************************************************* 1215*******************************************************************************/ 1216static boolean_t 1217x86_64_reloc_has_got(u_int _type) 1218{ 1219 enum reloc_type_x86_64 type = _type; 1220 1221 return (type == X86_64_RELOC_GOT_LOAD || type == X86_64_RELOC_GOT); 1222} 1223 1224/******************************************************************************* 1225*******************************************************************************/ 1226static kern_return_t 1227x86_64_process_reloc(const KXLDRelocator *relocator __unused, u_char *instruction, 1228 u_int length, u_int pcrel, kxld_addr_t _base_pc __unused, 1229 kxld_addr_t _link_pc, kxld_addr_t _link_disp, u_int _type, 1230 kxld_addr_t _target, kxld_addr_t _pair_target, boolean_t swap __unused) 1231{ 1232 kern_return_t rval = KERN_FAILURE; 1233 enum reloc_type_x86_64 type = _type; 1234 int32_t *instr32p = NULL; 1235 int32_t instr32 = 0; 1236 uint64_t *instr64p = NULL; 1237 uint64_t instr64 = 0; 1238 uint64_t target = _target; 1239 uint64_t pair_target = _pair_target; 1240 uint64_t link_pc = (uint64_t) _link_pc; 1241 uint64_t link_disp = (uint64_t) _link_disp; 1242 uint64_t adjustment = 0; 1243 1244 check(instruction); 1245 require_action(length == 2 || length == 3, 1246 finish, rval=KERN_FAILURE); 1247 1248 if (length == 2) { 1249 instr32p = (int32_t *) ((void *) instruction); 1250 instr32 = *instr32p; 1251 1252#if !KERNEL 1253 if (swap) instr32 = OSSwapInt32(instr32); 1254#endif 1255 1256 rval = check_for_direct_pure_virtual_call(relocator, instr32); 1257 require_noerr(rval, finish); 1258 1259 /* There are a number of different small adjustments for pc-relative 1260 * relocation entries. The general case is to subtract the size of the 1261 * relocation (represented by the length parameter), and it applies to 1262 * the GOT types and external SIGNED types. The non-external signed types 1263 * have a different adjustment corresponding to the specific type. 1264 */ 1265 switch (type) { 1266 case X86_64_RELOC_SIGNED: 1267 if (pair_target) { 1268 adjustment = 0; 1269 break; 1270 } 1271 /* Fall through */ 1272 case X86_64_RELOC_SIGNED_1: 1273 if (pair_target) { 1274 adjustment = 1; 1275 break; 1276 } 1277 /* Fall through */ 1278 case X86_64_RELOC_SIGNED_2: 1279 if (pair_target) { 1280 adjustment = 2; 1281 break; 1282 } 1283 /* Fall through */ 1284 case X86_64_RELOC_SIGNED_4: 1285 if (pair_target) { 1286 adjustment = 4; 1287 break; 1288 } 1289 /* Fall through */ 1290 case X86_64_RELOC_BRANCH: 1291 case X86_64_RELOC_GOT: 1292 case X86_64_RELOC_GOT_LOAD: 1293 adjustment = (1 << length); 1294 break; 1295 default: 1296 break; 1297 } 1298 1299 /* Perform the actual relocation. All of the 32-bit relocations are 1300 * pc-relative except for SUBTRACTOR, so a good chunk of the logic is 1301 * stuck in calculate_displacement_x86_64. The signed relocations are 1302 * a special case, because when they are non-external, the instruction 1303 * already contains the pre-relocation displacement, so we only need to 1304 * find the difference between how far the PC was relocated, and how 1305 * far the target is relocated. Since the target variable already 1306 * contains the difference between the target's base and link 1307 * addresses, we add the difference between the PC's base and link 1308 * addresses to the adjustment variable. This will yield the 1309 * appropriate displacement in calculate_displacement. 1310 */ 1311 switch (type) { 1312 case X86_64_RELOC_BRANCH: 1313 require_action(pcrel, finish, rval=KERN_FAILURE); 1314 adjustment += link_pc; 1315 break; 1316 case X86_64_RELOC_SIGNED: 1317 case X86_64_RELOC_SIGNED_1: 1318 case X86_64_RELOC_SIGNED_2: 1319 case X86_64_RELOC_SIGNED_4: 1320 require_action(pcrel, finish, rval=KERN_FAILURE); 1321 adjustment += (pair_target) ? (link_disp) : (link_pc); 1322 break; 1323 case X86_64_RELOC_GOT: 1324 case X86_64_RELOC_GOT_LOAD: 1325 require_action(pcrel, finish, rval=KERN_FAILURE); 1326 adjustment += link_pc; 1327 target = pair_target; 1328 break; 1329 case X86_64_RELOC_SUBTRACTOR: 1330 require_action(!pcrel, finish, rval=KERN_FAILURE); 1331 instr32 = (int32_t) (target - pair_target); 1332 break; 1333 case X86_64_RELOC_UNSIGNED: 1334 default: 1335 rval = KERN_FAILURE; 1336 goto finish; 1337 } 1338 1339 /* Call calculate_displacement for the pc-relative relocations */ 1340 if (pcrel) { 1341 rval = calculate_displacement_x86_64(target, adjustment, &instr32); 1342 require_noerr(rval, finish); 1343 } 1344 1345#if !KERNEL 1346 if (swap) instr32 = OSSwapInt32(instr32); 1347#endif 1348 1349 *instr32p = instr32; 1350 } else { 1351 instr64p = (uint64_t *) ((void *) instruction); 1352 instr64 = *instr64p; 1353 1354#if !KERNEL 1355 if (swap) instr64 = OSSwapInt64(instr64); 1356#endif 1357 1358 rval = check_for_direct_pure_virtual_call(relocator, (u_long) instr64); 1359 require_noerr(rval, finish); 1360 1361 switch (type) { 1362 case X86_64_RELOC_UNSIGNED: 1363 require_action(!pcrel, finish, rval=KERN_FAILURE); 1364 1365 instr64 += target; 1366 break; 1367 case X86_64_RELOC_SUBTRACTOR: 1368 require_action(!pcrel, finish, rval=KERN_FAILURE); 1369 1370 instr64 = target - pair_target; 1371 break; 1372 case X86_64_RELOC_SIGNED_1: 1373 case X86_64_RELOC_SIGNED_2: 1374 case X86_64_RELOC_SIGNED_4: 1375 case X86_64_RELOC_GOT_LOAD: 1376 case X86_64_RELOC_BRANCH: 1377 case X86_64_RELOC_SIGNED: 1378 case X86_64_RELOC_GOT: 1379 default: 1380 rval = KERN_FAILURE; 1381 goto finish; 1382 } 1383 1384#if !KERNEL 1385 if (swap) instr64 = OSSwapInt64(instr64); 1386#endif 1387 1388 *instr64p = instr64; 1389 } 1390 1391 rval = KERN_SUCCESS; 1392 1393finish: 1394 return rval; 1395} 1396 1397/******************************************************************************* 1398*******************************************************************************/ 1399static kern_return_t 1400calculate_displacement_x86_64(uint64_t target, uint64_t adjustment, 1401 int32_t *instr32) 1402{ 1403 kern_return_t rval = KERN_FAILURE; 1404 int64_t displacement; 1405 uint64_t difference; 1406 1407 displacement = *instr32 + target - adjustment; 1408 difference = ABSOLUTE_VALUE(displacement); 1409 require_action(difference < X86_64_RIP_RELATIVE_LIMIT, finish, 1410 rval=KERN_FAILURE; 1411 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogRelocationOverflow)); 1412 1413 *instr32 = (int32_t) displacement; 1414 rval = KERN_SUCCESS; 1415 1416finish: 1417 return rval; 1418} 1419#endif /* KXLD_USER_OR_X86_64 */ 1420 1421#if KXLD_USER_OR_ARM 1422/******************************************************************************* 1423*******************************************************************************/ 1424static boolean_t 1425arm_reloc_has_pair(u_int _type) 1426{ 1427 enum reloc_type_arm type = _type; 1428 1429 switch(type) { 1430 case ARM_RELOC_SECTDIFF: 1431 return TRUE; 1432 default: 1433 return FALSE; 1434 } 1435 return FALSE; 1436} 1437 1438/******************************************************************************* 1439*******************************************************************************/ 1440static u_int 1441arm_reloc_get_pair_type(u_int _prev_type __unused) 1442{ 1443 return ARM_RELOC_PAIR; 1444} 1445 1446/******************************************************************************* 1447*******************************************************************************/ 1448static boolean_t 1449arm_reloc_has_got(u_int _type __unused) 1450{ 1451 return FALSE; 1452} 1453 1454/******************************************************************************* 1455*******************************************************************************/ 1456static kern_return_t 1457arm_process_reloc(const KXLDRelocator *relocator __unused, u_char *instruction, 1458 u_int length, u_int pcrel, kxld_addr_t _base_pc __unused, 1459 kxld_addr_t _link_pc __unused, kxld_addr_t _link_disp __unused, 1460 u_int _type __unused, kxld_addr_t _target __unused, 1461 kxld_addr_t _pair_target __unused, boolean_t swap __unused) 1462{ 1463 kern_return_t rval = KERN_FAILURE; 1464 uint32_t *instr_addr = NULL; 1465 uint32_t instr_data = 0; 1466 uint32_t base_pc = (uint32_t) _base_pc; 1467 uint32_t link_pc = (uint32_t) _link_pc; 1468 uint32_t target = (uint32_t) _target; 1469 int32_t displacement = 0; 1470 enum reloc_type_arm type = _type; 1471 1472 check(instruction); 1473 require_action(length == 2, finish, rval=KERN_FAILURE); 1474 1475 if (pcrel) displacement = target + base_pc - link_pc; 1476 1477 instr_addr = (uint32_t *) ((void *) instruction); 1478 instr_data = *instr_addr; 1479 1480#if !KERNEL 1481 if (swap) instr_data = OSSwapInt32(instr_data); 1482#endif 1483 1484 rval = check_for_direct_pure_virtual_call(relocator, instr_data); 1485 require_noerr(rval, finish); 1486 1487 switch (type) { 1488 case ARM_RELOC_VANILLA: 1489 instr_data += target; 1490 break; 1491 1492 /* 1493 * If the displacement is 0 (the offset between the pc and the target has 1494 * not changed), then we don't need to do anything for BR24 and BR22 1495 * relocs. As it turns out, because kexts build with -mlong-calls all 1496 * relocations currently end up being either vanilla (handled above) or 1497 * BR22/BR24 with a displacement of 0. 1498 * We could handle other displacements here but to keep things simple, we 1499 * won't until it is needed (at which point the kernelcache will fail to 1500 * link) 1501 */ 1502 case ARM_RELOC_BR24: 1503 require_action(pcrel, finish, rval=KERN_FAILURE); 1504 require_action(displacement == 0, finish, rval=KERN_FAILURE); 1505 break; 1506 case ARM_THUMB_RELOC_BR22: 1507 require_action(pcrel, finish, rval=KERN_FAILURE); 1508 require_action(displacement == 0, finish, rval=KERN_FAILURE); 1509 break; 1510 1511 case ARM_RELOC_SECTDIFF: 1512 case ARM_RELOC_LOCAL_SECTDIFF: 1513 case ARM_RELOC_PB_LA_PTR: 1514 rval = KERN_FAILURE; 1515 goto finish; 1516 1517 case ARM_RELOC_PAIR: 1518 default: 1519 rval = KERN_FAILURE; 1520 goto finish; 1521 } 1522 1523#if !KERNEL 1524 if (swap) instr_data = OSSwapInt32(instr_data); 1525#endif 1526 1527 *instr_addr = instr_data; 1528 1529 rval = KERN_SUCCESS; 1530 1531finish: 1532 return rval; 1533} 1534 1535#endif /* KXLD_USER_OR_ARM */ 1536