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