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