1/* 2 * Copyright (c) 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-o/loader.h> 30#include <mach-o/reloc.h> 31#include <sys/types.h> 32 33#define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld" 34#include <AssertMacros.h> 35 36#include "kxld_reloc.h" 37#include "kxld_sect.h" 38#include "kxld_seg.h" 39#include "kxld_symtab.h" 40#include "kxld_util.h" 41 42static kern_return_t export_macho(const KXLDSect *sect, u_char *buf, u_long offset, 43 u_long bufsize); 44#if KXLD_USER_OR_ILP32 45static kern_return_t sect_export_macho_header_32(const KXLDSect *sect, u_char *buf, 46 u_long *header_offset, u_long header_size, u_long data_offset); 47#endif 48#if KXLD_USER_OR_LP64 49static kern_return_t sect_export_macho_header_64(const KXLDSect *sect, u_char *buf, 50 u_long *header_offset, u_long header_size, u_long data_offset); 51#endif 52 53#if KXLD_USER_OR_ILP32 54/******************************************************************************* 55*******************************************************************************/ 56kern_return_t 57kxld_sect_init_from_macho_32(KXLDSect *sect, u_char *macho, u_long *sect_offset, 58 u_int sectnum, const KXLDRelocator *relocator) 59{ 60 kern_return_t rval = KERN_FAILURE; 61 struct section *src = (struct section *) ((void *) (macho + *sect_offset)); 62 struct relocation_info *relocs = NULL; 63 64 check(sect); 65 check(macho); 66 check(src); 67 68 strlcpy(sect->segname, src->segname, sizeof(sect->segname)); 69 strlcpy(sect->sectname, src->sectname, sizeof(sect->sectname)); 70 sect->base_addr = src->addr; 71 sect->link_addr = src->addr; 72 sect->size = src->size; 73 sect->sectnum = sectnum; 74 sect->flags = src->flags; 75 sect->align = src->align; 76 sect->reserved1 = src->reserved1; 77 sect->reserved2 = src->reserved2; 78 79 if (src->offset) { 80 sect->data = macho + src->offset; 81 } else { 82 sect->data = NULL; 83 } 84 85 relocs = (struct relocation_info *) ((void *) (macho + src->reloff)); 86 87 rval = kxld_reloc_create_macho(§->relocs, relocator, 88 relocs, src->nreloc); 89 require_noerr(rval, finish); 90 91 *sect_offset += sizeof(*src); 92 rval = KERN_SUCCESS; 93 94finish: 95 if (rval) kxld_sect_deinit(sect); 96 97 return rval; 98} 99#endif /* KXLD_USER_OR_ILP32 */ 100 101#if KXLD_USER_OR_LP64 102/******************************************************************************* 103*******************************************************************************/ 104kern_return_t 105kxld_sect_init_from_macho_64(KXLDSect *sect, u_char *macho, u_long *sect_offset, 106 u_int sectnum, const KXLDRelocator *relocator) 107{ 108 kern_return_t rval = KERN_FAILURE; 109 struct section_64 *src = (struct section_64 *) ((void *) (macho + *sect_offset)); 110 struct relocation_info *relocs = NULL; 111 112 check(sect); 113 check(macho); 114 check(src); 115 116 strlcpy(sect->segname, src->segname, sizeof(sect->segname)); 117 strlcpy(sect->sectname, src->sectname, sizeof(sect->sectname)); 118 sect->base_addr = src->addr; 119 sect->link_addr = src->addr; 120 sect->size = src->size; 121 sect->sectnum = sectnum; 122 sect->flags = src->flags; 123 sect->align = src->align; 124 sect->reserved1 = src->reserved1; 125 sect->reserved2 = src->reserved2; 126 127 if (src->offset) { 128 sect->data = macho + src->offset; 129 } else { 130 sect->data = NULL; 131 } 132 133 relocs = (struct relocation_info *) ((void *) (macho + src->reloff)); 134 135 rval = kxld_reloc_create_macho(§->relocs, relocator, 136 relocs, src->nreloc); 137 require_noerr(rval, finish); 138 139 *sect_offset += sizeof(*src); 140 rval = KERN_SUCCESS; 141 142finish: 143 if (rval) kxld_sect_deinit(sect); 144 145 return rval; 146} 147#endif /* KXLD_USER_OR_LP64 */ 148 149#if KXLD_USER_OR_GOT 150/******************************************************************************* 151* Assumes GOT is comprised of kxld_addr_t entries 152*******************************************************************************/ 153kern_return_t 154kxld_sect_init_got(KXLDSect *sect, u_int ngots) 155{ 156 kern_return_t rval = KERN_FAILURE; 157 158 check(sect); 159 160 strlcpy(sect->segname, KXLD_SEG_GOT, sizeof(sect->segname)); 161 strlcpy(sect->sectname, KXLD_SECT_GOT, sizeof(sect->sectname)); 162 sect->base_addr = 0; 163 sect->link_addr = 0; 164 sect->flags = 0; 165 sect->align = 4; 166 sect->reserved1 = 0; 167 sect->reserved2 = 0; 168 169 sect->size = ngots * sizeof(kxld_addr_t); 170 sect->data = kxld_alloc((u_long) sect->size); 171 require_action(sect->data, finish, rval=KERN_RESOURCE_SHORTAGE); 172 173 sect->allocated = TRUE; 174 175 rval = KERN_SUCCESS; 176 177finish: 178 return rval; 179} 180#endif /* KXLD_USER_OR_GOT */ 181 182#if KXLD_USER_OR_COMMON 183/******************************************************************************* 184*******************************************************************************/ 185void 186kxld_sect_init_zerofill(KXLDSect *sect, const char *segname, 187 const char *sectname, kxld_size_t size, u_int align) 188{ 189 check(sect); 190 check(segname); 191 check(sectname); 192 193 strlcpy(sect->segname, segname, sizeof(sect->segname)); 194 strlcpy(sect->sectname, sectname, sizeof(sect->sectname)); 195 sect->size = size; 196 sect->align = align; 197 sect->base_addr = 0; 198 sect->link_addr = 0; 199 sect->flags = S_ZEROFILL; 200} 201#endif /* KXLD_USER_OR_COMMON */ 202 203/******************************************************************************* 204*******************************************************************************/ 205void 206kxld_sect_clear(KXLDSect *sect) 207{ 208 check(sect); 209 210 if (sect->allocated) { 211 kxld_free(sect->data, (u_long) sect->size); 212 sect->allocated = FALSE; 213 } 214 215 bzero(sect->sectname, sizeof(sect->sectname)); 216 bzero(sect->segname, sizeof(sect->segname)); 217 sect->data = NULL; 218 sect->base_addr = 0; 219 sect->link_addr = 0; 220 sect->size = 0; 221 sect->flags = 0; 222 sect->align = 0; 223 sect->reserved1 = 0; 224 sect->reserved2 = 0; 225 kxld_array_clear(§->relocs); 226} 227 228/******************************************************************************* 229*******************************************************************************/ 230void 231kxld_sect_deinit(KXLDSect *sect) 232{ 233 check(sect); 234 235 if (streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT))) { 236 kxld_free(sect->data, (u_long) sect->size); 237 } 238 239 kxld_array_deinit(§->relocs); 240 bzero(sect, sizeof(*sect)); 241} 242 243/******************************************************************************* 244*******************************************************************************/ 245u_int 246kxld_sect_get_num_relocs(const KXLDSect *sect) 247{ 248 check(sect); 249 250 return sect->relocs.nitems; 251} 252 253/******************************************************************************* 254*******************************************************************************/ 255u_long 256kxld_sect_get_macho_header_size(boolean_t is_32_bit) 257{ 258 if (is_32_bit) { 259 return sizeof(struct section); 260 } else { 261 return sizeof(struct section_64); 262 } 263} 264 265/******************************************************************************* 266*******************************************************************************/ 267u_long 268kxld_sect_get_macho_data_size(const KXLDSect *sect) 269{ 270 u_long size = 0; 271 272 check(sect); 273 274 if (sect->data) { 275 size = (u_long) sect->size; 276 } 277 278 return size; 279} 280 281#if KXLD_USER_OR_GOT 282/******************************************************************************* 283*******************************************************************************/ 284u_int 285kxld_sect_get_ngots(const KXLDSect *sect, const KXLDRelocator *relocator, 286 const KXLDSymtab *symtab) 287{ 288 const KXLDReloc *reloc = NULL; 289 KXLDSym *sym = NULL; 290 u_int ngots = 0; 291 u_int i = 0; 292 293 for (i = 0; i < sect->relocs.nitems; ++i) { 294 reloc = kxld_array_get_item(§->relocs, i); 295 296 if (relocator->reloc_has_got(reloc->reloc_type)) { 297 /* @TODO This assumes 64-bit symbols (which is valid at the 298 * moment since only x86_64 has a GOT) 299 */ 300 sym = kxld_reloc_get_symbol(relocator, reloc, sect->data, symtab); 301 if (!kxld_sym_is_got(sym)) { 302 kxld_sym_set_got(sym); 303 ++ngots; 304 } 305 } 306 } 307 308 return ngots; 309} 310#endif /* KXLD_USER_OR_GOT */ 311 312/******************************************************************************* 313* Each section must be aligned at a certain power of two. To figure out that 314* alignment, we mask for the low bits that may need to be adjusted. If they are 315* non zero, we then subtract them from the target alignment to find the offset, 316* and then add that offset to the link address. 317*******************************************************************************/ 318kxld_addr_t 319kxld_sect_align_address(const KXLDSect *sect, kxld_addr_t address) 320{ 321 return kxld_align_address(address, sect->align); 322} 323 324/******************************************************************************* 325*******************************************************************************/ 326kern_return_t 327kxld_sect_export_macho_to_file_buffer(const KXLDSect *sect, u_char *buf, 328 u_long *header_offset, u_long header_size, u_long *data_offset, 329 u_long data_size, boolean_t is_32_bit __unused) 330{ 331 kern_return_t rval = KERN_FAILURE; 332 333 check(sect); 334 check(buf); 335 check(header_offset); 336 check(data_offset); 337 338 /* If there is no data to export, we only need to write the header. We 339 * make it a separate call so that we don't modify data_offset. 340 */ 341 if (!sect->data) { 342 KXLD_3264_FUNC(is_32_bit, rval, 343 sect_export_macho_header_32, sect_export_macho_header_64, 344 sect, buf, header_offset, header_size, /* data_offset */ 0); 345 require_noerr(rval, finish); 346 } else { 347 *data_offset = (u_long) kxld_sect_align_address(sect, *data_offset); 348 349 KXLD_3264_FUNC(is_32_bit, rval, 350 sect_export_macho_header_32, sect_export_macho_header_64, 351 sect, buf, header_offset, header_size, *data_offset); 352 require_noerr(rval, finish); 353 354 rval = export_macho(sect, buf, *data_offset, data_size); 355 require_noerr(rval, finish); 356 357 *data_offset += (u_long) sect->size; 358 } 359 360 rval = KERN_SUCCESS; 361 362finish: 363 return rval; 364} 365 366/******************************************************************************* 367*******************************************************************************/ 368kern_return_t 369kxld_sect_export_macho_to_vm(const KXLDSect *sect, u_char *buf, 370 u_long *header_offset, u_long header_size, 371 kxld_addr_t link_addr, u_long data_size, 372 boolean_t is_32_bit __unused) 373{ 374 kern_return_t rval = KERN_FAILURE; 375 u_long data_offset = (u_long) (sect->link_addr - link_addr); 376 377 check(sect); 378 check(buf); 379 check(header_offset); 380 381 KXLD_3264_FUNC(is_32_bit, rval, 382 sect_export_macho_header_32, sect_export_macho_header_64, 383 sect, buf, header_offset, header_size, data_offset); 384 require_noerr(rval, finish); 385 386 rval = export_macho(sect, buf, data_offset, data_size); 387 require_noerr(rval, finish); 388 389 rval = KERN_SUCCESS; 390 391finish: 392 return rval; 393} 394 395/******************************************************************************* 396*******************************************************************************/ 397static kern_return_t 398export_macho(const KXLDSect *sect, u_char *buf, u_long offset, u_long bufsize) 399{ 400 kern_return_t rval = KERN_FAILURE; 401 402 check(sect); 403 check(buf); 404 405 if (!sect->data) { 406 rval = KERN_SUCCESS; 407 goto finish; 408 } 409 410 /* Verify that the section is properly aligned */ 411 412 require_action(kxld_sect_align_address(sect, offset) == offset, finish, 413 rval = KERN_FAILURE); 414 415 /* Verify that we have enough space to copy */ 416 417 require_action(sect->size <= bufsize - offset, finish, 418 rval=KERN_FAILURE); 419 420 /* Copy section data */ 421 422 switch (sect->flags & SECTION_TYPE) { 423 case S_NON_LAZY_SYMBOL_POINTERS: 424 case S_MOD_INIT_FUNC_POINTERS: 425 case S_MOD_TERM_FUNC_POINTERS: 426 case S_REGULAR: 427 case S_CSTRING_LITERALS: 428 case S_4BYTE_LITERALS: 429 case S_8BYTE_LITERALS: 430 case S_LITERAL_POINTERS: 431 case S_COALESCED: 432 case S_16BYTE_LITERALS: 433 case S_SYMBOL_STUBS: 434 memcpy(buf + offset, sect->data, (size_t)sect->size); 435 break; 436 case S_ZEROFILL: /* sect->data should be NULL, so we'll never get here */ 437 case S_LAZY_SYMBOL_POINTERS: 438 case S_GB_ZEROFILL: 439 case S_INTERPOSING: 440 case S_DTRACE_DOF: 441 default: 442 rval = KERN_FAILURE; 443 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO 444 "Invalid section type: %u.", sect->flags & SECTION_TYPE); 445 goto finish; 446 } 447 448 rval = KERN_SUCCESS; 449 450finish: 451 return rval; 452} 453 454#if KXLD_USER_OR_ILP32 455/******************************************************************************* 456*******************************************************************************/ 457static kern_return_t 458sect_export_macho_header_32(const KXLDSect *sect, u_char *buf, 459 u_long *header_offset, u_long header_size, u_long data_offset) 460{ 461 kern_return_t rval = KERN_FAILURE; 462 struct section *secthdr = NULL; 463 464 check(sect); 465 check(buf); 466 check(header_offset); 467 468 require_action(sizeof(*secthdr) <= header_size - *header_offset, finish, 469 rval=KERN_FAILURE); 470 secthdr = (struct section *) ((void *) (buf + *header_offset)); 471 *header_offset += sizeof(*secthdr); 472 473 /* Initalize header */ 474 475 strlcpy(secthdr->sectname, sect->sectname, sizeof(secthdr->sectname)); 476 strlcpy(secthdr->segname, sect->segname, sizeof(secthdr->segname)); 477 secthdr->addr = (uint32_t) sect->link_addr; 478 secthdr->size = (uint32_t) sect->size; 479 secthdr->offset = (uint32_t) ((sect->data) ? data_offset : 0); 480 secthdr->align = sect->align; 481 secthdr->reloff = 0; 482 secthdr->nreloc = 0; 483 secthdr->flags = sect->flags; 484 secthdr->reserved1 = sect->reserved1; 485 secthdr->reserved2 = sect->reserved2; 486 487 rval = KERN_SUCCESS; 488 489finish: 490 return rval; 491} 492#endif /* KXLD_USER_OR_ILP32 */ 493 494#if KXLD_USER_OR_LP64 495/******************************************************************************* 496*******************************************************************************/ 497static kern_return_t 498sect_export_macho_header_64(const KXLDSect *sect, u_char *buf, 499 u_long *header_offset, u_long header_size, u_long data_offset) 500{ 501 kern_return_t rval = KERN_FAILURE; 502 struct section_64 *secthdr = NULL; 503 504 check(sect); 505 check(buf); 506 check(header_offset); 507 508 require_action(sizeof(*secthdr) <= header_size - *header_offset, finish, 509 rval=KERN_FAILURE); 510 secthdr = (struct section_64 *) ((void *) (buf + *header_offset)); 511 *header_offset += sizeof(*secthdr); 512 513 /* Initalize header */ 514 515 strlcpy(secthdr->sectname, sect->sectname, sizeof(secthdr->sectname)); 516 strlcpy(secthdr->segname, sect->segname, sizeof(secthdr->segname)); 517 secthdr->addr = (uint64_t) sect->link_addr; 518 secthdr->size = (uint64_t) sect->size; 519 secthdr->offset = (uint32_t) ((sect->data) ? data_offset : 0); 520 secthdr->align = sect->align; 521 secthdr->reloff = 0; 522 secthdr->nreloc = 0; 523 secthdr->flags = sect->flags; 524 secthdr->reserved1 = sect->reserved1; 525 secthdr->reserved2 = sect->reserved2; 526 527 rval = KERN_SUCCESS; 528 529finish: 530 return rval; 531} 532#endif /* KXLD_USER_OR_LP64 */ 533 534#if KXLD_USER_OR_COMMON 535/******************************************************************************* 536*******************************************************************************/ 537kxld_size_t 538kxld_sect_grow(KXLDSect *sect, kxld_size_t nbytes, u_int align) 539{ 540 kxld_size_t size = kxld_align_address(sect->size, align); 541 542 if (align > sect->align) sect->align = align; 543 sect->size = size + nbytes; 544 545 return size; 546} 547#endif /* KXLD_USER_OR_COMMON */ 548 549/******************************************************************************* 550*******************************************************************************/ 551void 552kxld_sect_relocate(KXLDSect *sect, kxld_addr_t link_addr) 553{ 554 sect->link_addr = kxld_sect_align_address(sect, 555 sect->link_addr + link_addr); 556} 557 558#if KXLD_USER_OR_GOT 559/******************************************************************************* 560*******************************************************************************/ 561kern_return_t 562kxld_sect_populate_got(KXLDSect *sect, KXLDSymtab *symtab, 563 boolean_t swap __unused) 564{ 565 kern_return_t rval = KERN_FAILURE; 566 KXLDSymtabIterator iter; 567 KXLDSym *sym = NULL; 568 kxld_addr_t *entry = NULL; 569 kxld_addr_t entry_addr = 0; 570 571 check(sect); 572 check(symtab); 573 require(streq_safe(sect->segname, KXLD_SEG_GOT, sizeof(KXLD_SEG_GOT)), 574 finish); 575 require(streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT)), 576 finish); 577 578 kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_got, FALSE); 579 580 entry = (kxld_addr_t *) sect->data; 581 entry_addr = sect->link_addr; 582 while ((sym = kxld_symtab_iterator_get_next(&iter))) { 583 *entry = sym->link_addr; 584 sym->got_addr = entry_addr; 585 586#if !KERNEL 587 if (swap) *entry = OSSwapInt64(*entry); 588#endif /* !KERNEL */ 589 590 ++entry; 591 entry_addr += sizeof(*entry); 592 } 593 594 rval = KERN_SUCCESS; 595 596finish: 597 return rval; 598} 599#endif /* KXLD_USER_OR_GOT */ 600 601/******************************************************************************* 602*******************************************************************************/ 603kern_return_t 604kxld_sect_process_relocs(KXLDSect *sect, KXLDRelocator *relocator) 605{ 606 kern_return_t rval = KERN_FAILURE; 607 KXLDReloc *reloc = NULL; 608 u_int i = 0; 609 610 for (i = 0; i < sect->relocs.nitems; ++i) { 611 reloc = kxld_array_get_item(§->relocs, i); 612 rval = kxld_relocator_process_sect_reloc(relocator, reloc, sect); 613 require_noerr(rval, finish); 614 } 615 616 rval = KERN_SUCCESS; 617finish: 618 return rval; 619} 620 621