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 <stdint.h> 30#include <sys/types.h> 31#include <mach-o/nlist.h> 32#include <mach-o/stab.h> 33 34#define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld" 35#include <AssertMacros.h> 36 37#include "kxld_sect.h" 38#include "kxld_sym.h" 39#include "kxld_util.h" 40 41#define CXX_PREFIX "__Z" 42#define VTABLE_PREFIX CXX_PREFIX "TV" 43#define OSOBJ_PREFIX CXX_PREFIX "N" 44#define RESERVED_TOKEN "_RESERVED" 45#define METACLASS_TOKEN "10gMetaClassE" 46#define SUPER_METACLASS_POINTER_TOKEN "10superClassE" 47#define METACLASS_VTABLE_PREFIX VTABLE_PREFIX "N" 48#define METACLASS_VTABLE_SUFFIX "9MetaClassE" 49#define CXX_PURE_VIRTUAL "___cxa_pure_virtual" 50#define FINAL_CLASS_TOKEN "14__OSFinalClassEv" 51 52/******************************************************************************* 53* Prototypes 54*******************************************************************************/ 55 56static kern_return_t init_predicates(KXLDSym *sym, u_char n_type, u_short n_desc) 57 __attribute__((nonnull)); 58static void init_sym_sectnum(KXLDSym *sym, u_int n_sect) 59 __attribute__((nonnull)); 60static kern_return_t extract_inner_string(const char *str, const char *prefix, 61 const char *suffix, char *buf, u_long len); 62 63#if KXLD_USER_OR_ILP32 64/******************************************************************************* 65*******************************************************************************/ 66kern_return_t 67kxld_sym_init_from_macho32(KXLDSym *sym, char *strtab, const struct nlist *src) 68{ 69 kern_return_t rval = KERN_FAILURE; 70 71 check(sym); 72 check(strtab); 73 check(src); 74 75 bzero(sym, sizeof(*sym)); 76 sym->name = strtab + src->n_un.n_strx; 77 sym->type = src->n_type; 78 sym->desc = src->n_desc; 79 sym->base_addr = src->n_value; 80 sym->link_addr = sym->base_addr; 81 82 rval = init_predicates(sym, src->n_type, src->n_desc); 83 require_noerr(rval, finish); 84 85 (void) init_sym_sectnum(sym, src->n_sect); 86 87 if (kxld_sym_is_indirect(sym)) { 88 sym->alias = strtab + src->n_value; 89 } 90 91 rval = KERN_SUCCESS; 92 93finish: 94 return rval; 95} 96#endif /* KXLD_USER_OR_ILP32 */ 97 98#if KXLD_USER_OR_LP64 99/******************************************************************************* 100*******************************************************************************/ 101kern_return_t 102kxld_sym_init_from_macho64(KXLDSym *sym, char *strtab, const struct nlist_64 *src) 103{ 104 kern_return_t rval = KERN_FAILURE; 105 106 check(sym); 107 check(strtab); 108 check(src); 109 110 bzero(sym, sizeof(*sym)); 111 sym->name = strtab + src->n_un.n_strx; 112 sym->type = src->n_type; 113 sym->desc = src->n_desc; 114 sym->base_addr = src->n_value; 115 sym->link_addr = sym->base_addr; 116 117 rval = init_predicates(sym, src->n_type, src->n_desc); 118 require_noerr(rval, finish); 119 120 (void) init_sym_sectnum(sym, src->n_sect); 121 122 if (kxld_sym_is_indirect(sym)) { 123 sym->alias = strtab + src->n_value; 124 } 125 126 rval = KERN_SUCCESS; 127 128finish: 129 return rval; 130} 131#endif /* KXLD_USER_OR_LP64 */ 132 133/******************************************************************************* 134*******************************************************************************/ 135void 136kxld_sym_init_absolute(KXLDSym *sym, char *name, kxld_addr_t link_addr) 137{ 138 check(sym); 139 check(name); 140 141 bzero(sym, sizeof(*sym)); 142 143 sym->name = name; 144 sym->link_addr = link_addr; 145 sym->type = N_ABS | N_EXT; 146 sym->sectnum = NO_SECT; 147 148 init_predicates(sym, N_ABS | N_EXT, 0); 149 sym->is_resolved = TRUE; 150} 151 152/******************************************************************************* 153*******************************************************************************/ 154static kern_return_t 155init_predicates(KXLDSym *sym, u_char n_type, u_short n_desc) 156{ 157 kern_return_t rval = KERN_FAILURE; 158 159 check(sym); 160 161 /* The type field is interpreted differently for normal symbols and stabs */ 162 if (n_type & N_STAB) { 163 sym->is_stab = 1; 164 165 switch (n_type) { 166 /* Labeled as NO_SECT in stab.h */ 167 case N_GSYM: 168 case N_FNAME: 169 case N_RSYM: 170 case N_SSYM: 171 case N_LSYM: 172 case N_BINCL: 173 case N_PARAMS: 174 case N_VERSION: 175 case N_OLEVEL: 176 case N_PSYM: 177 case N_EINCL: 178 case N_EXCL: 179 case N_BCOMM: 180 case N_LENG: 181 case N_OPT: 182 case N_OSO: 183 sym->is_absolute = 1; 184 break; 185 /* Labeled as n_sect in stab.h */ 186 case N_FUN: 187 case N_STSYM: 188 case N_LCSYM: 189 case N_BNSYM: 190 case N_SLINE: 191 case N_ENSYM: 192 case N_SO: 193 case N_SOL: 194 case N_ENTRY: 195 case N_ECOMM: 196 case N_ECOML: 197 /* These are labeled as NO_SECT in stab.h, but they are actually 198 * section-based on OS X. We must mark them as such so they get 199 * relocated. 200 */ 201 case N_RBRAC: 202 case N_LBRAC: 203 sym->is_section = 1; 204 break; 205 default: 206 rval = KERN_FAILURE; 207 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO 208 "Invalid N_STAB symbol type: %u.", n_type); 209 goto finish; 210 } 211 212 /* Don't care about the C++ predicates for stabs */ 213 214 } else { 215 u_char type = n_type & N_TYPE; 216 217 /* The first set of type fields are mutually exclusive, so they can be 218 * set with a switch statement. 219 */ 220 switch (type) { 221 case N_ABS: 222 sym->is_absolute = 1; 223 break; 224 case N_SECT: 225 sym->is_section = 1; 226 break; 227 case N_UNDF: 228 if (sym->base_addr) { 229 sym->is_common = 1; 230 } else { 231 sym->is_undefined = 1; 232 } 233 break; 234 case N_INDR: 235 sym->is_indirect = 1; 236 break; 237 default: 238 rval = KERN_FAILURE; 239 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO 240 "Invalid symbol type: %u.", type); 241 goto finish; 242 } 243 244 /* Set the type-independent fields */ 245 if ((n_type & N_EXT) && !(n_type & N_PEXT)) { 246 sym->is_external = 1; 247 } 248 249 if (n_desc & N_DESC_DISCARDED) { 250 sym->is_obsolete = 1; 251 } 252 253 if (n_desc & N_WEAK_REF) { 254 sym->is_weak = 1; 255 } 256 257 if (n_desc & N_ARM_THUMB_DEF) { 258 sym->is_thumb = 1; 259 sym->base_addr |= 1; 260 sym->link_addr |= 1; 261 } 262 263 /* Set the C++-specific fields */ 264 if ((streq_safe(CXX_PREFIX, sym->name, const_strlen(CXX_PREFIX)))) { 265 sym->is_cxx = 1; 266 267 if (streq_safe(sym->name, METACLASS_VTABLE_PREFIX, 268 const_strlen(METACLASS_VTABLE_PREFIX))) 269 { 270 sym->is_meta_vtable = 1; 271 } else if (streq_safe(sym->name, VTABLE_PREFIX, 272 const_strlen(VTABLE_PREFIX))) 273 { 274 sym->is_class_vtable = 1; 275 } else if (kxld_strstr(sym->name, RESERVED_TOKEN)) { 276 sym->is_padslot = 1; 277 } else if (kxld_strstr(sym->name, METACLASS_TOKEN)) { 278 sym->is_metaclass = 1; 279 } else if (kxld_strstr(sym->name, SUPER_METACLASS_POINTER_TOKEN)) { 280 sym->is_super_metaclass_pointer = 1; 281 } 282 } else if (kxld_sym_name_is_pure_virtual(sym->name)) { 283 sym->is_cxx = 1; 284 sym->is_pure_virtual = 1; 285 } 286 } 287 288 rval = KERN_SUCCESS; 289 290finish: 291 return rval; 292} 293 294/******************************************************************************* 295*******************************************************************************/ 296static void 297init_sym_sectnum(KXLDSym *sym, u_int n_sect) 298{ 299 /* The n_sect field is set to 0 when the symbol is not section-based, and 300 * the number of the section in which the symbol exists otherwise. 301 * Sometimes, symbols can be labeled as section-based, so we make sure that 302 * they have a valid section number, and set them as absolute if they don't. 303 */ 304 305 if (kxld_sym_is_section(sym)) { 306 if (n_sect) { 307 /* Convert the section number to an index into the section index */ 308 sym->sectnum = n_sect - 1; 309 } else { 310 sym->is_absolute = 1; 311 sym->is_section = 0; 312 } 313 } 314 315} 316 317/******************************************************************************* 318*******************************************************************************/ 319void 320kxld_sym_deinit(KXLDSym *sym __unused) 321{ 322 check(sym); 323} 324 325/******************************************************************************* 326*******************************************************************************/ 327void 328kxld_sym_destroy(KXLDSym *sym) 329{ 330 check(sym); 331 kxld_sym_deinit(sym); 332 kxld_free(sym, sizeof(*sym)); 333} 334 335 336/******************************************************************************* 337*******************************************************************************/ 338boolean_t 339kxld_sym_is_absolute(const KXLDSym *sym) 340{ 341 check(sym); 342 343 return (0 != sym->is_absolute); 344} 345 346/******************************************************************************* 347*******************************************************************************/ 348boolean_t 349kxld_sym_is_section(const KXLDSym *sym) 350{ 351 check(sym); 352 353 return (0 != sym->is_section); 354} 355 356/******************************************************************************* 357*******************************************************************************/ 358boolean_t 359kxld_sym_is_defined(const KXLDSym *sym) 360{ 361 check(sym); 362 363 return ((kxld_sym_is_absolute(sym) || kxld_sym_is_section(sym)) && 364 !kxld_sym_is_replaced(sym)); 365} 366 367 368/******************************************************************************* 369*******************************************************************************/ 370boolean_t 371kxld_sym_is_defined_locally(const KXLDSym *sym) 372{ 373 check(sym); 374 375 return (kxld_sym_is_defined(sym) && !sym->is_resolved); 376} 377 378/******************************************************************************* 379*******************************************************************************/ 380boolean_t 381kxld_sym_is_external(const KXLDSym *sym) 382{ 383 check(sym); 384 385 return (0 != sym->is_external); 386} 387 388/******************************************************************************* 389*******************************************************************************/ 390boolean_t 391kxld_sym_is_exported(const KXLDSym *sym) 392{ 393 check(sym); 394 395 return (kxld_sym_is_defined_locally(sym) && kxld_sym_is_external(sym)); 396} 397 398/******************************************************************************* 399*******************************************************************************/ 400boolean_t 401kxld_sym_is_undefined(const KXLDSym *sym) 402{ 403 check(sym); 404 405 return (0 != sym->is_undefined); 406} 407 408/******************************************************************************* 409*******************************************************************************/ 410boolean_t 411kxld_sym_is_indirect(const KXLDSym *sym) 412{ 413 check(sym); 414 415 return (0 != sym->is_indirect); 416} 417 418/******************************************************************************* 419*******************************************************************************/ 420boolean_t 421kxld_sym_is_replaced(const KXLDSym *sym) 422{ 423 check(sym); 424 425 return (0 != sym->is_replaced); 426} 427 428/******************************************************************************* 429*******************************************************************************/ 430boolean_t 431kxld_sym_is_common(const KXLDSym *sym) 432{ 433 check(sym); 434 435 return (0 != sym->is_common); 436} 437 438/******************************************************************************* 439*******************************************************************************/ 440boolean_t 441kxld_sym_is_unresolved(const KXLDSym *sym) 442{ 443 return ((kxld_sym_is_undefined(sym) && !kxld_sym_is_replaced(sym)) || 444 kxld_sym_is_indirect(sym) || kxld_sym_is_common(sym)); 445} 446 447/******************************************************************************* 448*******************************************************************************/ 449boolean_t 450kxld_sym_is_obsolete(const KXLDSym *sym) 451{ 452 return (0 != sym->is_obsolete); 453} 454 455#if KXLD_USER_OR_GOT 456/******************************************************************************* 457*******************************************************************************/ 458boolean_t 459kxld_sym_is_got(const KXLDSym *sym) 460{ 461 check(sym); 462 463 return (0 != sym->is_got); 464} 465#endif /* KXLD_USER_OR_GOT */ 466 467/******************************************************************************* 468*******************************************************************************/ 469boolean_t 470kxld_sym_is_stab(const KXLDSym *sym) 471{ 472 check(sym); 473 474 return (0 != sym->is_stab); 475} 476 477/******************************************************************************* 478*******************************************************************************/ 479boolean_t 480kxld_sym_is_weak(const KXLDSym *sym) 481{ 482 check(sym); 483 484 return (0 != sym->is_weak); 485} 486 487/******************************************************************************* 488*******************************************************************************/ 489boolean_t 490kxld_sym_is_cxx(const KXLDSym *sym) 491{ 492 check(sym); 493 494 return (0 != sym->is_cxx); 495} 496 497/******************************************************************************* 498*******************************************************************************/ 499boolean_t 500kxld_sym_is_pure_virtual(const KXLDSym *sym) 501{ 502 return (0 != sym->is_pure_virtual); 503} 504 505/******************************************************************************* 506*******************************************************************************/ 507boolean_t 508kxld_sym_is_vtable(const KXLDSym *sym) 509{ 510 check(sym); 511 512 return kxld_sym_is_class_vtable(sym) || kxld_sym_is_metaclass_vtable(sym); 513} 514 515/******************************************************************************* 516*******************************************************************************/ 517boolean_t 518kxld_sym_is_class_vtable(const KXLDSym *sym) 519{ 520 check(sym); 521 522 return (0 != sym->is_class_vtable); 523} 524 525/******************************************************************************* 526*******************************************************************************/ 527boolean_t 528kxld_sym_is_metaclass_vtable(const KXLDSym *sym) 529{ 530 check(sym); 531 532 return (0 != sym->is_meta_vtable); 533} 534 535/******************************************************************************* 536*******************************************************************************/ 537boolean_t 538kxld_sym_is_padslot(const KXLDSym *sym) 539{ 540 check(sym); 541 542 return (0 != sym->is_padslot); 543} 544 545/******************************************************************************* 546*******************************************************************************/ 547boolean_t 548kxld_sym_is_metaclass(const KXLDSym *sym) 549{ 550 check(sym); 551 552 return (0 != sym->is_metaclass); 553} 554 555/******************************************************************************* 556*******************************************************************************/ 557boolean_t 558kxld_sym_is_super_metaclass_pointer(const KXLDSym *sym) 559{ 560 check(sym); 561 562 return (0 != sym->is_super_metaclass_pointer); 563} 564 565/******************************************************************************* 566*******************************************************************************/ 567boolean_t 568kxld_sym_name_is_pure_virtual(const char *name) 569{ 570 return streq_safe(CXX_PURE_VIRTUAL, name, sizeof(CXX_PURE_VIRTUAL)); 571} 572 573/******************************************************************************* 574*******************************************************************************/ 575boolean_t 576kxld_sym_name_is_padslot(const char *name) 577{ 578 check(name); 579 580 return (kxld_strstr(name, RESERVED_TOKEN) != 0); 581} 582 583/******************************************************************************* 584*******************************************************************************/ 585u_int 586kxld_sym_get_section_offset(const KXLDSym *sym, const KXLDSect *sect) 587{ 588 check(sym); 589 590 return (u_int) (sym->base_addr - sect->base_addr); 591} 592 593#if KXLD_USER_OR_COMMON 594/******************************************************************************* 595*******************************************************************************/ 596kxld_size_t 597kxld_sym_get_common_size(const KXLDSym *sym) 598{ 599 return sym->base_addr; 600} 601 602/******************************************************************************* 603*******************************************************************************/ 604u_int 605kxld_sym_get_common_align(const KXLDSym *sym) 606{ 607 u_int align = GET_COMM_ALIGN(sym->desc); 608 if (!align) align = 3; 609 610 return align; 611} 612#endif /* KXLD_USER_OR_COMMON */ 613 614/******************************************************************************* 615*******************************************************************************/ 616kern_return_t 617kxld_sym_get_class_name_from_metaclass(const KXLDSym *sym, 618 char class_name[], u_long class_name_len) 619{ 620 kern_return_t rval = KERN_FAILURE; 621 622 check(sym); 623 require_action(kxld_sym_is_metaclass(sym), finish, rval=KERN_FAILURE); 624 625 rval = extract_inner_string(sym->name, OSOBJ_PREFIX, METACLASS_TOKEN, 626 class_name, class_name_len); 627 require_noerr(rval, finish); 628 629 rval = KERN_SUCCESS; 630finish: 631 return rval; 632} 633 634/******************************************************************************* 635*******************************************************************************/ 636kern_return_t 637kxld_sym_get_class_name_from_super_metaclass_pointer(const KXLDSym *sym, 638 char class_name[], u_long class_name_len) 639{ 640 kern_return_t rval = KERN_FAILURE; 641 642 check(sym); 643 require_action(kxld_sym_is_super_metaclass_pointer(sym), finish, 644 rval=KERN_FAILURE); 645 646 rval = extract_inner_string(sym->name, OSOBJ_PREFIX, 647 SUPER_METACLASS_POINTER_TOKEN, class_name, class_name_len); 648 require_noerr(rval, finish); 649 650 rval = KERN_SUCCESS; 651finish: 652 return rval; 653} 654 655/******************************************************************************* 656*******************************************************************************/ 657kern_return_t 658kxld_sym_get_class_name_from_vtable(const KXLDSym *sym, 659 char class_name[], u_long class_name_len) 660{ 661 kern_return_t rval = KERN_FAILURE; 662 663 check(sym); 664 require_action(kxld_sym_is_class_vtable(sym), finish, rval=KERN_FAILURE); 665 666 rval = kxld_sym_get_class_name_from_vtable_name(sym->name, 667 class_name, class_name_len); 668 require_noerr(rval, finish); 669 670 rval = KERN_SUCCESS; 671 672finish: 673 return rval; 674} 675 676/******************************************************************************* 677*******************************************************************************/ 678kern_return_t 679kxld_sym_get_class_name_from_vtable_name(const char *vtable_name, 680 char class_name[], u_long class_name_len) 681{ 682 kern_return_t rval = KERN_FAILURE; 683 684 check(vtable_name); 685 686 rval = extract_inner_string(vtable_name, VTABLE_PREFIX, NULL, 687 class_name, class_name_len); 688 require_noerr(rval, finish); 689 690 rval = KERN_SUCCESS; 691finish: 692 return rval; 693} 694 695/******************************************************************************* 696*******************************************************************************/ 697kern_return_t 698kxld_sym_get_vtable_name_from_class_name(const char *class_name, 699 char vtable_name[], u_long vtable_name_len) 700{ 701 kern_return_t rval = KERN_FAILURE; 702 u_long outlen = 0; 703 704 check(class_name); 705 check(vtable_name); 706 707 outlen = strlcpy(vtable_name, VTABLE_PREFIX, vtable_name_len); 708 require_action(outlen < vtable_name_len, finish, 709 rval=KERN_FAILURE); 710 711 outlen = strlcat(vtable_name, class_name, vtable_name_len); 712 require_action(outlen < vtable_name_len, finish, 713 rval=KERN_FAILURE); 714 715 rval = KERN_SUCCESS; 716finish: 717 return rval; 718} 719 720/******************************************************************************* 721*******************************************************************************/ 722kern_return_t 723kxld_sym_get_meta_vtable_name_from_class_name(const char *class_name, 724 char meta_vtable_name[], u_long meta_vtable_name_len) 725{ 726 kern_return_t rval = KERN_FAILURE; 727 u_long outlen = 0; 728 729 check(class_name); 730 check(meta_vtable_name); 731 732 outlen = strlcpy(meta_vtable_name, METACLASS_VTABLE_PREFIX, 733 meta_vtable_name_len); 734 require_action(outlen < meta_vtable_name_len, finish, 735 rval=KERN_FAILURE); 736 737 outlen = strlcat(meta_vtable_name, class_name, meta_vtable_name_len); 738 require_action(outlen < meta_vtable_name_len, finish, 739 rval=KERN_FAILURE); 740 741 outlen = strlcat(meta_vtable_name, METACLASS_VTABLE_SUFFIX, 742 meta_vtable_name_len); 743 require_action(outlen < meta_vtable_name_len, finish, 744 rval=KERN_FAILURE); 745 746 rval = KERN_SUCCESS; 747finish: 748 return rval; 749} 750 751/******************************************************************************* 752*******************************************************************************/ 753kern_return_t 754kxld_sym_get_final_sym_name_from_class_name(const char *class_name, 755 char final_sym_name[], u_long final_sym_name_len) 756{ 757 kern_return_t rval = KERN_FAILURE; 758 u_long outlen = 0; 759 760 check(class_name); 761 check(final_sym_name); 762 763 outlen = strlcpy(final_sym_name, OSOBJ_PREFIX, final_sym_name_len); 764 require_action(outlen < final_sym_name_len, finish, 765 rval=KERN_FAILURE); 766 767 outlen = strlcat(final_sym_name, class_name, final_sym_name_len); 768 require_action(outlen < final_sym_name_len, finish, 769 rval=KERN_FAILURE); 770 771 outlen = strlcat(final_sym_name, FINAL_CLASS_TOKEN, final_sym_name_len); 772 require_action(outlen < final_sym_name_len, finish, 773 rval=KERN_FAILURE); 774 775 rval = KERN_SUCCESS; 776 777finish: 778 return rval; 779} 780 781/******************************************************************************* 782*******************************************************************************/ 783u_long 784kxld_sym_get_function_prefix_from_class_name(const char *class_name, 785 char function_prefix[], u_long function_prefix_len) 786{ 787 u_long rval = 0; 788 u_long outlen = 0; 789 790 check(class_name); 791 check(function_prefix); 792 793 outlen = strlcpy(function_prefix, OSOBJ_PREFIX, function_prefix_len); 794 require(outlen < function_prefix_len, finish); 795 796 outlen = strlcat(function_prefix, class_name, function_prefix_len); 797 require(outlen < function_prefix_len, finish); 798 799 rval = outlen; 800finish: 801 return rval; 802} 803 804/******************************************************************************* 805*******************************************************************************/ 806static kern_return_t 807extract_inner_string(const char *str, const char *prefix, const char *suffix, 808 char *buf, u_long len) 809{ 810 kern_return_t rval = KERN_FAILURE; 811 u_long prelen = 0, suflen = 0, striplen = 0; 812 813 check(str); 814 check(buf); 815 816 prelen = (prefix) ? strlen(prefix) : 0; 817 suflen = (suffix) ? strlen(suffix) : 0; 818 striplen = strlen(str) - prelen - suflen; 819 820 require_action(striplen < len, finish, rval=KERN_FAILURE); 821 822 strncpy(buf, str + prelen, striplen); 823 buf[striplen] = '\0'; 824 825 rval = KERN_SUCCESS; 826finish: 827 return rval; 828} 829 830#if KXLD_USER_OR_GOT 831/******************************************************************************* 832*******************************************************************************/ 833void 834kxld_sym_set_got(KXLDSym *sym) 835{ 836 sym->is_got = 1; 837} 838#endif /* KXLD_USER_OR_GOT */ 839 840/******************************************************************************* 841*******************************************************************************/ 842void 843kxld_sym_relocate(KXLDSym *sym, const KXLDSect *sect) 844{ 845 if (kxld_sym_is_section(sym)) { 846 sym->link_addr = sym->base_addr - sect->base_addr + sect->link_addr; 847 sym->relocated_sectnum = sect->sectnum; 848 } 849} 850 851#if KXLD_USER_OR_ILP32 852/******************************************************************************* 853*******************************************************************************/ 854kern_return_t 855kxld_sym_export_macho_32(const KXLDSym *sym, u_char *_nl, char *strtab, 856 u_long *stroff, u_long strsize) 857{ 858 kern_return_t rval = KERN_FAILURE; 859 struct nlist *nl = (struct nlist *) ((void *) _nl); 860 char *str = NULL; 861 long bytes = 0; 862 863 check(sym); 864 check(nl); 865 check(strtab); 866 check(stroff); 867 868 bytes = strlen(sym->name) + 1; 869 require_action((u_long)bytes <= strsize - *stroff, finish, 870 rval = KERN_FAILURE); 871 872 nl->n_type = sym->type; 873 nl->n_sect = (kxld_sym_is_section(sym)) ? sym->relocated_sectnum + 1 : 0; 874 nl->n_desc = sym->desc; 875 nl->n_un.n_strx = (uint32_t) *stroff; 876 nl->n_value = (uint32_t) sym->link_addr; 877 if (sym->is_thumb) { 878 nl->n_value &= ~0x1U; 879 } 880 881 str = (char *) (strtab + *stroff); 882 strlcpy(str, sym->name, strsize - *stroff); 883 884 *stroff += bytes; 885 rval = KERN_SUCCESS; 886 887finish: 888 return rval; 889} 890#endif /* KXLD_USER_OR_ILP32 */ 891 892#if KXLD_USER_OR_LP64 893/******************************************************************************* 894*******************************************************************************/ 895kern_return_t 896kxld_sym_export_macho_64(const KXLDSym *sym, u_char *_nl, char *strtab, 897 u_long *stroff, u_long strsize) 898{ 899 kern_return_t rval = KERN_FAILURE; 900 struct nlist_64 *nl = (struct nlist_64 *) ((void *) _nl); 901 char *str = NULL; 902 long bytes = 0; 903 904 check(sym); 905 check(nl); 906 check(strtab); 907 check(stroff); 908 909 bytes = strlen(sym->name) + 1; 910 require_action((u_long)bytes <= strsize - *stroff, finish, 911 rval = KERN_FAILURE); 912 913 nl->n_type = sym->type; 914 nl->n_sect = (kxld_sym_is_section(sym)) ? sym->relocated_sectnum + 1 : 0; 915 nl->n_desc = sym->desc; 916 nl->n_un.n_strx = (uint32_t) *stroff; 917 nl->n_value = (uint64_t) sym->link_addr; 918 if (sym->is_thumb) { 919 nl->n_value &= ~0x1ULL; 920 } 921 922 str = (char *) (strtab + *stroff); 923 strlcpy(str, sym->name, strsize - *stroff); 924 925 *stroff += bytes; 926 rval = KERN_SUCCESS; 927 928finish: 929 return rval; 930} 931#endif /* KXLD_USER_OR_LP64 */ 932 933/******************************************************************************* 934*******************************************************************************/ 935kern_return_t 936kxld_sym_resolve(KXLDSym *sym, kxld_addr_t addr) 937{ 938 kern_return_t rval = KERN_FAILURE; 939 940 check(sym); 941 942 require_action(kxld_sym_is_undefined(sym) || kxld_sym_is_indirect(sym), 943 finish, rval=KERN_FAILURE); 944 945 /* Set the n_list data types */ 946 947 sym->link_addr = addr; 948 sym->type = N_ABS | N_EXT; 949 sym->sectnum = NO_SECT; 950 951 /* Set the predicate bits for an externally resolved symbol. */ 952 953 sym->is_external = TRUE; 954 sym->is_absolute = TRUE; 955 sym->is_resolved = TRUE; 956 957 /* Clear the predicate bits for types that can be resolved */ 958 959 sym->is_undefined = FALSE; 960 sym->is_indirect = FALSE; 961 962 rval = KERN_SUCCESS; 963 964finish: 965 966 return rval; 967} 968 969#if KXLD_USER_OR_COMMON 970/******************************************************************************* 971*******************************************************************************/ 972kern_return_t 973kxld_sym_resolve_common(KXLDSym *sym, u_int sectnum, kxld_addr_t base_addr) 974{ 975 kern_return_t rval = KERN_FAILURE; 976 977 check(sym); 978 979 require_action(kxld_sym_is_common(sym), finish, 980 rval=KERN_FAILURE); 981 982 sym->base_addr = base_addr; 983 sym->link_addr = base_addr; 984 sym->type = N_SECT | N_EXT; 985 sym->sectnum = sectnum; 986 sym->desc = 0; 987 988 sym->is_absolute = FALSE; 989 sym->is_section = TRUE; 990 sym->is_undefined = FALSE; 991 sym->is_indirect = FALSE; 992 sym->is_common = FALSE; 993 sym->is_external = TRUE; 994 995 rval = KERN_SUCCESS; 996 997finish: 998 999 return rval; 1000} 1001#endif /* KXLD_USER_OR_COMMON */ 1002 1003/******************************************************************************* 1004*******************************************************************************/ 1005void 1006kxld_sym_delete(KXLDSym *sym) 1007{ 1008 check(sym); 1009 1010 bzero(sym, sizeof(*sym)); 1011 sym->is_replaced = TRUE; 1012} 1013 1014 1015/******************************************************************************* 1016*******************************************************************************/ 1017void 1018kxld_sym_patch(KXLDSym *sym) 1019{ 1020 check(sym); 1021 1022 sym->is_replaced = TRUE; 1023} 1024 1025/******************************************************************************* 1026*******************************************************************************/ 1027void 1028kxld_sym_mark_private(KXLDSym *sym) 1029{ 1030 check(sym); 1031 1032 sym->type |= N_PEXT; 1033 sym->is_external = FALSE; 1034} 1035 1036