xref: /xnu-11215.41.3/libkern/kxld/kxld_sym.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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
kxld_sym_init_from_macho32(KXLDSym * sym,char * strtab,const struct nlist * src)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
kxld_sym_init_from_macho64(KXLDSym * sym,char * strtab,const struct nlist_64 * src)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
kxld_sym_init_absolute(KXLDSym * sym,char * name,kxld_addr_t link_addr)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
init_predicates(KXLDSym * sym,u_char n_type,u_short n_desc)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
init_sym_sectnum(KXLDSym * sym,u_int n_sect)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
kxld_sym_deinit(KXLDSym * sym __unused)320 kxld_sym_deinit(KXLDSym *sym __unused)
321 {
322 	check(sym);
323 }
324 
325 /*******************************************************************************
326 *******************************************************************************/
327 void
kxld_sym_destroy(KXLDSym * sym)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
kxld_sym_is_absolute(const KXLDSym * sym)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
kxld_sym_is_section(const KXLDSym * sym)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
kxld_sym_is_defined(const KXLDSym * sym)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
kxld_sym_is_defined_locally(const KXLDSym * sym)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
kxld_sym_is_external(const KXLDSym * sym)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
kxld_sym_is_exported(const KXLDSym * sym)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
kxld_sym_is_undefined(const KXLDSym * sym)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
kxld_sym_is_indirect(const KXLDSym * sym)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
kxld_sym_is_replaced(const KXLDSym * sym)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
kxld_sym_is_common(const KXLDSym * sym)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
kxld_sym_is_unresolved(const KXLDSym * sym)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
kxld_sym_is_obsolete(const KXLDSym * sym)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
kxld_sym_is_got(const KXLDSym * sym)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
kxld_sym_is_stab(const KXLDSym * sym)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
kxld_sym_is_weak(const KXLDSym * sym)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
kxld_sym_is_cxx(const KXLDSym * sym)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
kxld_sym_is_pure_virtual(const KXLDSym * sym)500 kxld_sym_is_pure_virtual(const KXLDSym *sym)
501 {
502 	return 0 != sym->is_pure_virtual;
503 }
504 
505 /*******************************************************************************
506 *******************************************************************************/
507 boolean_t
kxld_sym_is_vtable(const KXLDSym * sym)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
kxld_sym_is_class_vtable(const KXLDSym * sym)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
kxld_sym_is_metaclass_vtable(const KXLDSym * sym)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
kxld_sym_is_padslot(const KXLDSym * sym)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
kxld_sym_is_metaclass(const KXLDSym * sym)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
kxld_sym_is_super_metaclass_pointer(const KXLDSym * sym)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
kxld_sym_name_is_pure_virtual(const char * name)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
kxld_sym_name_is_padslot(const char * name)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
kxld_sym_get_section_offset(const KXLDSym * sym,const KXLDSect * sect)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
kxld_sym_get_common_size(const KXLDSym * sym)597 kxld_sym_get_common_size(const KXLDSym *sym)
598 {
599 	return sym->base_addr;
600 }
601 
602 /*******************************************************************************
603 *******************************************************************************/
604 u_int
kxld_sym_get_common_align(const KXLDSym * sym)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
kxld_sym_get_class_name_from_metaclass(const KXLDSym * sym,char class_name[],u_long class_name_len)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
kxld_sym_get_class_name_from_super_metaclass_pointer(const KXLDSym * sym,char class_name[],u_long class_name_len)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
kxld_sym_get_class_name_from_vtable(const KXLDSym * sym,char class_name[],u_long class_name_len)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
kxld_sym_get_class_name_from_vtable_name(const char * vtable_name,char class_name[],u_long class_name_len)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
kxld_sym_get_vtable_name_from_class_name(const char * class_name,char vtable_name[],u_long vtable_name_len)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
kxld_sym_get_meta_vtable_name_from_class_name(const char * class_name,char meta_vtable_name[],u_long meta_vtable_name_len)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
kxld_sym_get_final_sym_name_from_class_name(const char * class_name,char final_sym_name[],u_long final_sym_name_len)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
kxld_sym_get_function_prefix_from_class_name(const char * class_name,char function_prefix[],u_long function_prefix_len)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
extract_inner_string(const char * str,const char * prefix,const char * suffix,char * buf,u_long len)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
kxld_sym_set_got(KXLDSym * sym)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
kxld_sym_relocate(KXLDSym * sym,const KXLDSect * sect)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
kxld_sym_export_macho_32(const KXLDSym * sym,u_char * _nl,char * strtab,u_long * stroff,u_long strsize)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
kxld_sym_export_macho_64(const KXLDSym * sym,u_char * _nl,char * strtab,u_long * stroff,u_long strsize)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
kxld_sym_resolve(KXLDSym * sym,kxld_addr_t addr)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
kxld_sym_resolve_common(KXLDSym * sym,u_int sectnum,kxld_addr_t base_addr)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
kxld_sym_delete(KXLDSym * sym)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
kxld_sym_patch(KXLDSym * sym)1022 kxld_sym_patch(KXLDSym *sym)
1023 {
1024 	check(sym);
1025 
1026 	sym->is_replaced = TRUE;
1027 }
1028 
1029 /*******************************************************************************
1030 *******************************************************************************/
1031 void
kxld_sym_mark_private(KXLDSym * sym)1032 kxld_sym_mark_private(KXLDSym *sym)
1033 {
1034 	check(sym);
1035 
1036 	sym->type |= N_PEXT;
1037 	sym->is_external = FALSE;
1038 }
1039