]> git.saurik.com Git - apple/xnu.git/blob - libkern/kxld/kxld_sym.c
xnu-3247.1.106.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->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->is_stab = 1;
164
165 switch (n_type) {
166 /* Labeled as NO_SECT in stab.h */
167 case N_GSYM:
168 case N_FNAME:
169 case N_RSYM:
170 case N_SSYM:
171 case N_LSYM:
172 case N_BINCL:
173 case N_PARAMS:
174 case N_VERSION:
175 case N_OLEVEL:
176 case N_PSYM:
177 case N_EINCL:
178 case N_EXCL:
179 case N_BCOMM:
180 case N_LENG:
181 case N_OPT:
182 case N_OSO:
183 sym->is_absolute = 1;
184 break;
185 /* Labeled as n_sect in stab.h */
186 case N_FUN:
187 case N_STSYM:
188 case N_LCSYM:
189 case N_BNSYM:
190 case N_SLINE:
191 case N_ENSYM:
192 case N_SO:
193 case N_SOL:
194 case N_ENTRY:
195 case N_ECOMM:
196 case N_ECOML:
197 /* These are labeled as NO_SECT in stab.h, but they are actually
198 * section-based on OS X. We must mark them as such so they get
199 * relocated.
200 */
201 case N_RBRAC:
202 case N_LBRAC:
203 sym->is_section = 1;
204 break;
205 default:
206 rval = KERN_FAILURE;
207 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
208 "Invalid N_STAB symbol type: %u.", n_type);
209 goto finish;
210 }
211
212 /* Don't care about the C++ predicates for stabs */
213
214 } else {
215 u_char type = n_type & N_TYPE;
216
217 /* The first set of type fields are mutually exclusive, so they can be
218 * set with a switch statement.
219 */
220 switch (type) {
221 case N_ABS:
222 sym->is_absolute = 1;
223 break;
224 case N_SECT:
225 sym->is_section = 1;
226 break;
227 case N_UNDF:
228 if (sym->base_addr) {
229 sym->is_common = 1;
230 } else {
231 sym->is_undefined = 1;
232 }
233 break;
234 case N_INDR:
235 sym->is_indirect = 1;
236 break;
237 default:
238 rval = KERN_FAILURE;
239 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
240 "Invalid symbol type: %u.", type);
241 goto finish;
242 }
243
244 /* Set the type-independent fields */
245 if ((n_type & N_EXT) && !(n_type & N_PEXT)) {
246 sym->is_external = 1;
247 }
248
249 if (n_desc & N_DESC_DISCARDED) {
250 sym->is_obsolete = 1;
251 }
252
253 if (n_desc & N_WEAK_REF) {
254 sym->is_weak = 1;
255 }
256
257 if (n_desc & N_ARM_THUMB_DEF) {
258 sym->is_thumb = 1;
259 sym->base_addr |= 1;
260 sym->link_addr |= 1;
261 }
262
263 /* Set the C++-specific fields */
264 if (!strncmp(CXX_PREFIX, sym->name, const_strlen(CXX_PREFIX))) {
265 sym->is_cxx = 1;
266
267 if (streq_safe(sym->name, METACLASS_VTABLE_PREFIX,
268 const_strlen(METACLASS_VTABLE_PREFIX)))
269 {
270 sym->is_meta_vtable = 1;
271 } else if (streq_safe(sym->name, VTABLE_PREFIX,
272 const_strlen(VTABLE_PREFIX)))
273 {
274 sym->is_class_vtable = 1;
275 } else if (kxld_strstr(sym->name, RESERVED_TOKEN)) {
276 sym->is_padslot = 1;
277 } else if (kxld_strstr(sym->name, METACLASS_TOKEN)) {
278 sym->is_metaclass = 1;
279 } else if (kxld_strstr(sym->name, SUPER_METACLASS_POINTER_TOKEN)) {
280 sym->is_super_metaclass_pointer = 1;
281 }
282 } else if (kxld_sym_name_is_pure_virtual(sym->name)) {
283 sym->is_cxx = 1;
284 sym->is_pure_virtual = 1;
285 }
286 }
287
288 rval = KERN_SUCCESS;
289
290 finish:
291 return rval;
292 }
293
294 /*******************************************************************************
295 *******************************************************************************/
296 static void
297 init_sym_sectnum(KXLDSym *sym, u_int n_sect)
298 {
299 /* The n_sect field is set to 0 when the symbol is not section-based, and
300 * the number of the section in which the symbol exists otherwise.
301 * Sometimes, symbols can be labeled as section-based, so we make sure that
302 * they have a valid section number, and set them as absolute if they don't.
303 */
304
305 if (kxld_sym_is_section(sym)) {
306 if (n_sect) {
307 /* Convert the section number to an index into the section index */
308 sym->sectnum = n_sect - 1;
309 } else {
310 sym->is_absolute = 1;
311 sym->is_section = 0;
312 }
313 }
314
315 }
316
317 /*******************************************************************************
318 *******************************************************************************/
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 (kxld_strstr(name, RESERVED_TOKEN) != 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) align = 3;
609
610 return align;
611 }
612 #endif /* KXLD_USER_OR_COMMON */
613
614 /*******************************************************************************
615 *******************************************************************************/
616 kern_return_t
617 kxld_sym_get_class_name_from_metaclass(const KXLDSym *sym,
618 char class_name[], u_long class_name_len)
619 {
620 kern_return_t rval = KERN_FAILURE;
621
622 check(sym);
623 require_action(kxld_sym_is_metaclass(sym), finish, rval=KERN_FAILURE);
624
625 rval = extract_inner_string(sym->name, OSOBJ_PREFIX, METACLASS_TOKEN,
626 class_name, class_name_len);
627 require_noerr(rval, finish);
628
629 rval = KERN_SUCCESS;
630 finish:
631 return rval;
632 }
633
634 /*******************************************************************************
635 *******************************************************************************/
636 kern_return_t
637 kxld_sym_get_class_name_from_super_metaclass_pointer(const KXLDSym *sym,
638 char class_name[], u_long class_name_len)
639 {
640 kern_return_t rval = KERN_FAILURE;
641
642 check(sym);
643 require_action(kxld_sym_is_super_metaclass_pointer(sym), finish,
644 rval=KERN_FAILURE);
645
646 rval = extract_inner_string(sym->name, OSOBJ_PREFIX,
647 SUPER_METACLASS_POINTER_TOKEN, class_name, class_name_len);
648 require_noerr(rval, finish);
649
650 rval = KERN_SUCCESS;
651 finish:
652 return rval;
653 }
654
655 /*******************************************************************************
656 *******************************************************************************/
657 kern_return_t
658 kxld_sym_get_class_name_from_vtable(const KXLDSym *sym,
659 char class_name[], u_long class_name_len)
660 {
661 kern_return_t rval = KERN_FAILURE;
662
663 check(sym);
664 require_action(kxld_sym_is_class_vtable(sym), finish, rval=KERN_FAILURE);
665
666 rval = kxld_sym_get_class_name_from_vtable_name(sym->name,
667 class_name, class_name_len);
668 require_noerr(rval, finish);
669
670 rval = KERN_SUCCESS;
671
672 finish:
673 return rval;
674 }
675
676 /*******************************************************************************
677 *******************************************************************************/
678 kern_return_t
679 kxld_sym_get_class_name_from_vtable_name(const char *vtable_name,
680 char class_name[], u_long class_name_len)
681 {
682 kern_return_t rval = KERN_FAILURE;
683
684 check(vtable_name);
685
686 rval = extract_inner_string(vtable_name, VTABLE_PREFIX, NULL,
687 class_name, class_name_len);
688 require_noerr(rval, finish);
689
690 rval = KERN_SUCCESS;
691 finish:
692 return rval;
693 }
694
695 /*******************************************************************************
696 *******************************************************************************/
697 kern_return_t
698 kxld_sym_get_vtable_name_from_class_name(const char *class_name,
699 char vtable_name[], u_long vtable_name_len)
700 {
701 kern_return_t rval = KERN_FAILURE;
702 u_long outlen = 0;
703
704 check(class_name);
705 check(vtable_name);
706
707 outlen = strlcpy(vtable_name, VTABLE_PREFIX, vtable_name_len);
708 require_action(outlen < vtable_name_len, finish,
709 rval=KERN_FAILURE);
710
711 outlen = strlcat(vtable_name, class_name, vtable_name_len);
712 require_action(outlen < vtable_name_len, finish,
713 rval=KERN_FAILURE);
714
715 rval = KERN_SUCCESS;
716 finish:
717 return rval;
718 }
719
720 /*******************************************************************************
721 *******************************************************************************/
722 kern_return_t
723 kxld_sym_get_meta_vtable_name_from_class_name(const char *class_name,
724 char meta_vtable_name[], u_long meta_vtable_name_len)
725 {
726 kern_return_t rval = KERN_FAILURE;
727 u_long outlen = 0;
728
729 check(class_name);
730 check(meta_vtable_name);
731
732 outlen = strlcpy(meta_vtable_name, METACLASS_VTABLE_PREFIX,
733 meta_vtable_name_len);
734 require_action(outlen < meta_vtable_name_len, finish,
735 rval=KERN_FAILURE);
736
737 outlen = strlcat(meta_vtable_name, class_name, meta_vtable_name_len);
738 require_action(outlen < meta_vtable_name_len, finish,
739 rval=KERN_FAILURE);
740
741 outlen = strlcat(meta_vtable_name, METACLASS_VTABLE_SUFFIX,
742 meta_vtable_name_len);
743 require_action(outlen < meta_vtable_name_len, finish,
744 rval=KERN_FAILURE);
745
746 rval = KERN_SUCCESS;
747 finish:
748 return rval;
749 }
750
751 /*******************************************************************************
752 *******************************************************************************/
753 kern_return_t
754 kxld_sym_get_final_sym_name_from_class_name(const char *class_name,
755 char final_sym_name[], u_long final_sym_name_len)
756 {
757 kern_return_t rval = KERN_FAILURE;
758 u_long outlen = 0;
759
760 check(class_name);
761 check(final_sym_name);
762
763 outlen = strlcpy(final_sym_name, OSOBJ_PREFIX, final_sym_name_len);
764 require_action(outlen < final_sym_name_len, finish,
765 rval=KERN_FAILURE);
766
767 outlen = strlcat(final_sym_name, class_name, final_sym_name_len);
768 require_action(outlen < final_sym_name_len, finish,
769 rval=KERN_FAILURE);
770
771 outlen = strlcat(final_sym_name, FINAL_CLASS_TOKEN, final_sym_name_len);
772 require_action(outlen < final_sym_name_len, finish,
773 rval=KERN_FAILURE);
774
775 rval = KERN_SUCCESS;
776
777 finish:
778 return rval;
779 }
780
781 /*******************************************************************************
782 *******************************************************************************/
783 u_long
784 kxld_sym_get_function_prefix_from_class_name(const char *class_name,
785 char function_prefix[], u_long function_prefix_len)
786 {
787 u_long rval = 0;
788 u_long outlen = 0;
789
790 check(class_name);
791 check(function_prefix);
792
793 outlen = strlcpy(function_prefix, OSOBJ_PREFIX, function_prefix_len);
794 require(outlen < function_prefix_len, finish);
795
796 outlen = strlcat(function_prefix, class_name, function_prefix_len);
797 require(outlen < function_prefix_len, finish);
798
799 rval = outlen;
800 finish:
801 return rval;
802 }
803
804 /*******************************************************************************
805 *******************************************************************************/
806 static kern_return_t
807 extract_inner_string(const char *str, const char *prefix, const char *suffix,
808 char *buf, u_long len)
809 {
810 kern_return_t rval = KERN_FAILURE;
811 u_long prelen = 0, suflen = 0, striplen = 0;
812
813 check(str);
814 check(buf);
815
816 prelen = (prefix) ? strlen(prefix) : 0;
817 suflen = (suffix) ? strlen(suffix) : 0;
818 striplen = strlen(str) - prelen - suflen;
819
820 require_action(striplen < len, finish, rval=KERN_FAILURE);
821
822 strncpy(buf, str + prelen, striplen);
823 buf[striplen] = '\0';
824
825 rval = KERN_SUCCESS;
826 finish:
827 return rval;
828 }
829
830 #if KXLD_USER_OR_GOT
831 /*******************************************************************************
832 *******************************************************************************/
833 void
834 kxld_sym_set_got(KXLDSym *sym)
835 {
836 sym->is_got = 1;
837 }
838 #endif /* KXLD_USER_OR_GOT */
839
840 /*******************************************************************************
841 *******************************************************************************/
842 void
843 kxld_sym_relocate(KXLDSym *sym, const KXLDSect *sect)
844 {
845 if (kxld_sym_is_section(sym)) {
846 sym->link_addr = sym->base_addr - sect->base_addr + sect->link_addr;
847 sym->relocated_sectnum = sect->sectnum;
848 }
849 }
850
851 #if KXLD_USER_OR_ILP32
852 /*******************************************************************************
853 *******************************************************************************/
854 kern_return_t
855 kxld_sym_export_macho_32(const KXLDSym *sym, u_char *_nl, char *strtab,
856 u_long *stroff, u_long strsize)
857 {
858 kern_return_t rval = KERN_FAILURE;
859 struct nlist *nl = (struct nlist *) ((void *) _nl);
860 char *str = NULL;
861 long bytes = 0;
862
863 check(sym);
864 check(nl);
865 check(strtab);
866 check(stroff);
867
868 bytes = strlen(sym->name) + 1;
869 require_action((u_long)bytes <= strsize - *stroff, finish,
870 rval = KERN_FAILURE);
871
872 nl->n_type = sym->type;
873 nl->n_sect = (kxld_sym_is_section(sym)) ? sym->relocated_sectnum + 1 : 0;
874 nl->n_desc = sym->desc;
875 nl->n_un.n_strx = (uint32_t) *stroff;
876 nl->n_value = (uint32_t) sym->link_addr;
877 if (sym->is_thumb) {
878 nl->n_value &= ~0x1U;
879 }
880
881 str = (char *) (strtab + *stroff);
882 strlcpy(str, sym->name, strsize - *stroff);
883
884 *stroff += bytes;
885 rval = KERN_SUCCESS;
886
887 finish:
888 return rval;
889 }
890 #endif /* KXLD_USER_OR_ILP32 */
891
892 #if KXLD_USER_OR_LP64
893 /*******************************************************************************
894 *******************************************************************************/
895 kern_return_t
896 kxld_sym_export_macho_64(const KXLDSym *sym, u_char *_nl, char *strtab,
897 u_long *stroff, u_long strsize)
898 {
899 kern_return_t rval = KERN_FAILURE;
900 struct nlist_64 *nl = (struct nlist_64 *) ((void *) _nl);
901 char *str = NULL;
902 long bytes = 0;
903
904 check(sym);
905 check(nl);
906 check(strtab);
907 check(stroff);
908
909 bytes = strlen(sym->name) + 1;
910 require_action((u_long)bytes <= strsize - *stroff, finish,
911 rval = KERN_FAILURE);
912
913 nl->n_type = sym->type;
914 nl->n_sect = (kxld_sym_is_section(sym)) ? sym->relocated_sectnum + 1 : 0;
915 nl->n_desc = sym->desc;
916 nl->n_un.n_strx = (uint32_t) *stroff;
917 nl->n_value = (uint64_t) sym->link_addr;
918 if (sym->is_thumb) {
919 nl->n_value &= ~0x1ULL;
920 }
921
922 str = (char *) (strtab + *stroff);
923 strlcpy(str, sym->name, strsize - *stroff);
924
925 *stroff += bytes;
926 rval = KERN_SUCCESS;
927
928 finish:
929 return rval;
930 }
931 #endif /* KXLD_USER_OR_LP64 */
932
933 /*******************************************************************************
934 *******************************************************************************/
935 kern_return_t
936 kxld_sym_resolve(KXLDSym *sym, kxld_addr_t addr)
937 {
938 kern_return_t rval = KERN_FAILURE;
939
940 check(sym);
941
942 require_action(kxld_sym_is_undefined(sym) || kxld_sym_is_indirect(sym),
943 finish, rval=KERN_FAILURE);
944
945 /* Set the n_list data types */
946
947 sym->link_addr = addr;
948 sym->type = N_ABS | N_EXT;
949 sym->sectnum = NO_SECT;
950
951 /* Set the predicate bits for an externally resolved symbol. */
952
953 sym->is_external = TRUE;
954 sym->is_absolute = TRUE;
955 sym->is_resolved = TRUE;
956
957 /* Clear the predicate bits for types that can be resolved */
958
959 sym->is_undefined = FALSE;
960 sym->is_indirect = FALSE;
961
962 rval = KERN_SUCCESS;
963
964 finish:
965
966 return rval;
967 }
968
969 #if KXLD_USER_OR_COMMON
970 /*******************************************************************************
971 *******************************************************************************/
972 kern_return_t
973 kxld_sym_resolve_common(KXLDSym *sym, u_int sectnum, kxld_addr_t base_addr)
974 {
975 kern_return_t rval = KERN_FAILURE;
976
977 check(sym);
978
979 require_action(kxld_sym_is_common(sym), finish,
980 rval=KERN_FAILURE);
981
982 sym->base_addr = base_addr;
983 sym->link_addr = base_addr;
984 sym->type = N_SECT | N_EXT;
985 sym->sectnum = sectnum;
986 sym->desc = 0;
987
988 sym->is_absolute = FALSE;
989 sym->is_section = TRUE;
990 sym->is_undefined = FALSE;
991 sym->is_indirect = FALSE;
992 sym->is_common = FALSE;
993 sym->is_external = TRUE;
994
995 rval = KERN_SUCCESS;
996
997 finish:
998
999 return rval;
1000 }
1001 #endif /* KXLD_USER_OR_COMMON */
1002
1003 /*******************************************************************************
1004 *******************************************************************************/
1005 void
1006 kxld_sym_delete(KXLDSym *sym)
1007 {
1008 check(sym);
1009
1010 bzero(sym, sizeof(*sym));
1011 sym->is_replaced = TRUE;
1012 }
1013
1014
1015 /*******************************************************************************
1016 *******************************************************************************/
1017 void
1018 kxld_sym_patch(KXLDSym *sym)
1019 {
1020 check(sym);
1021
1022 sym->is_replaced = TRUE;
1023 }
1024
1025 /*******************************************************************************
1026 *******************************************************************************/
1027 void
1028 kxld_sym_mark_private(KXLDSym *sym)
1029 {
1030 check(sym);
1031
1032 sym->type |= N_PEXT;
1033 sym->is_external = FALSE;
1034 }
1035