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