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