]> git.saurik.com Git - apple/xnu.git/blame - libkern/kxld/kxld_sym.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_sym.c
CommitLineData
b0d623f7
A
1/*
2 * Copyright (c) 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
b0d623f7
A
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.
0a7de745 14 *
b0d623f7
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
b0d623f7
A
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.
0a7de745 25 *
b0d623f7
A
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
56static kern_return_t init_predicates(KXLDSym *sym, u_char n_type, u_short n_desc)
0a7de745 57__attribute__((nonnull));
b0d623f7 58static void init_sym_sectnum(KXLDSym *sym, u_int n_sect)
0a7de745
A
59__attribute__((nonnull));
60static kern_return_t extract_inner_string(const char *str, const char *prefix,
b0d623f7
A
61 const char *suffix, char *buf, u_long len);
62
63#if KXLD_USER_OR_ILP32
64/*******************************************************************************
65*******************************************************************************/
66kern_return_t
0a7de745 67kxld_sym_init_from_macho32(KXLDSym *sym, char *strtab, const struct nlist *src)
b0d623f7 68{
0a7de745 69 kern_return_t rval = KERN_FAILURE;
b0d623f7 70
0a7de745
A
71 check(sym);
72 check(strtab);
73 check(src);
b0d623f7 74
0a7de745
A
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;
b0d623f7 81
0a7de745
A
82 rval = init_predicates(sym, src->n_type, src->n_desc);
83 require_noerr(rval, finish);
b0d623f7 84
0a7de745 85 (void) init_sym_sectnum(sym, src->n_sect);
b0d623f7 86
0a7de745
A
87 if (kxld_sym_is_indirect(sym)) {
88 sym->alias = strtab + src->n_value;
89 }
90
91 rval = KERN_SUCCESS;
b0d623f7
A
92
93finish:
0a7de745 94 return rval;
b0d623f7
A
95}
96#endif /* KXLD_USER_OR_ILP32 */
97
98#if KXLD_USER_OR_LP64
99/*******************************************************************************
100*******************************************************************************/
101kern_return_t
0a7de745 102kxld_sym_init_from_macho64(KXLDSym *sym, char *strtab, const struct nlist_64 *src)
b0d623f7 103{
0a7de745
A
104 kern_return_t rval = KERN_FAILURE;
105
106 check(sym);
107 check(strtab);
108 check(src);
b0d623f7 109
0a7de745
A
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;
b0d623f7 116
cb323159
A
117 if (!strcmp("__ZN15OSMetaClassBase25_RESERVEDOSMetaClassBase3Ev", sym->name)) {
118 sym->name = (char *)(uintptr_t) "__ZN15OSMetaClassBase8DispatchE5IORPC";
119 }
120
0a7de745
A
121 rval = init_predicates(sym, src->n_type, src->n_desc);
122 require_noerr(rval, finish);
b0d623f7 123
0a7de745 124 (void) init_sym_sectnum(sym, src->n_sect);
b0d623f7 125
0a7de745
A
126 if (kxld_sym_is_indirect(sym)) {
127 sym->alias = strtab + src->n_value;
128 }
b0d623f7 129
0a7de745 130 rval = KERN_SUCCESS;
b0d623f7
A
131
132finish:
0a7de745 133 return rval;
b0d623f7
A
134}
135#endif /* KXLD_USER_OR_LP64 */
136
137/*******************************************************************************
138*******************************************************************************/
0a7de745 139void
b0d623f7
A
140kxld_sym_init_absolute(KXLDSym *sym, char *name, kxld_addr_t link_addr)
141{
0a7de745
A
142 check(sym);
143 check(name);
b0d623f7 144
0a7de745 145 bzero(sym, sizeof(*sym));
b0d623f7 146
0a7de745
A
147 sym->name = name;
148 sym->link_addr = link_addr;
149 sym->type = N_ABS | N_EXT;
150 sym->sectnum = NO_SECT;
b0d623f7 151
0a7de745
A
152 init_predicates(sym, N_ABS | N_EXT, 0);
153 sym->is_resolved = TRUE;
b0d623f7
A
154}
155
156/*******************************************************************************
157*******************************************************************************/
158static kern_return_t
159init_predicates(KXLDSym *sym, u_char n_type, u_short n_desc)
160{
0a7de745
A
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;
f427ee49 276 } else if (strnstr(sym->name, RESERVED_TOKEN, strlen(sym->name))) {
0a7de745 277 sym->is_padslot = 1;
f427ee49 278 } else if (strnstr(sym->name, METACLASS_TOKEN, strlen(sym->name))) {
0a7de745 279 sym->is_metaclass = 1;
f427ee49 280 } else if (strnstr(sym->name, SUPER_METACLASS_POINTER_TOKEN, strlen(sym->name))) {
0a7de745
A
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;
b0d623f7
A
290
291finish:
0a7de745 292 return rval;
b0d623f7
A
293}
294
295/*******************************************************************************
296*******************************************************************************/
297static void
298init_sym_sectnum(KXLDSym *sym, u_int n_sect)
299{
0a7de745
A
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 }
b0d623f7
A
315}
316
317/*******************************************************************************
318*******************************************************************************/
319void
320kxld_sym_deinit(KXLDSym *sym __unused)
321{
0a7de745 322 check(sym);
b0d623f7
A
323}
324
325/*******************************************************************************
326*******************************************************************************/
327void
328kxld_sym_destroy(KXLDSym *sym)
329{
0a7de745
A
330 check(sym);
331 kxld_sym_deinit(sym);
332 kxld_free(sym, sizeof(*sym));
b0d623f7
A
333}
334
335
336/*******************************************************************************
337*******************************************************************************/
338boolean_t
339kxld_sym_is_absolute(const KXLDSym *sym)
340{
0a7de745 341 check(sym);
b0d623f7 342
0a7de745 343 return 0 != sym->is_absolute;
b0d623f7
A
344}
345
346/*******************************************************************************
347*******************************************************************************/
348boolean_t
349kxld_sym_is_section(const KXLDSym *sym)
350{
0a7de745 351 check(sym);
b0d623f7 352
0a7de745 353 return 0 != sym->is_section;
b0d623f7
A
354}
355
356/*******************************************************************************
357*******************************************************************************/
358boolean_t
359kxld_sym_is_defined(const KXLDSym *sym)
360{
0a7de745 361 check(sym);
b0d623f7 362
0a7de745
A
363 return (kxld_sym_is_absolute(sym) || kxld_sym_is_section(sym)) &&
364 !kxld_sym_is_replaced(sym);
b0d623f7
A
365}
366
367
368/*******************************************************************************
369*******************************************************************************/
370boolean_t
371kxld_sym_is_defined_locally(const KXLDSym *sym)
372{
0a7de745 373 check(sym);
b0d623f7 374
0a7de745 375 return kxld_sym_is_defined(sym) && !sym->is_resolved;
b0d623f7
A
376}
377
378/*******************************************************************************
379*******************************************************************************/
380boolean_t
381kxld_sym_is_external(const KXLDSym *sym)
382{
0a7de745 383 check(sym);
b0d623f7 384
0a7de745 385 return 0 != sym->is_external;
b0d623f7
A
386}
387
388/*******************************************************************************
389*******************************************************************************/
390boolean_t
391kxld_sym_is_exported(const KXLDSym *sym)
392{
0a7de745 393 check(sym);
b0d623f7 394
0a7de745 395 return kxld_sym_is_defined_locally(sym) && kxld_sym_is_external(sym);
b0d623f7
A
396}
397
398/*******************************************************************************
399*******************************************************************************/
400boolean_t
401kxld_sym_is_undefined(const KXLDSym *sym)
402{
0a7de745 403 check(sym);
b0d623f7 404
0a7de745 405 return 0 != sym->is_undefined;
b0d623f7
A
406}
407
408/*******************************************************************************
409*******************************************************************************/
410boolean_t
411kxld_sym_is_indirect(const KXLDSym *sym)
412{
0a7de745 413 check(sym);
b0d623f7 414
0a7de745 415 return 0 != sym->is_indirect;
6d2010ae
A
416}
417
418/*******************************************************************************
419*******************************************************************************/
420boolean_t
421kxld_sym_is_replaced(const KXLDSym *sym)
422{
0a7de745 423 check(sym);
6d2010ae 424
0a7de745 425 return 0 != sym->is_replaced;
b0d623f7
A
426}
427
428/*******************************************************************************
429*******************************************************************************/
430boolean_t
431kxld_sym_is_common(const KXLDSym *sym)
432{
0a7de745 433 check(sym);
b0d623f7 434
0a7de745 435 return 0 != sym->is_common;
b0d623f7
A
436}
437
438/*******************************************************************************
439*******************************************************************************/
440boolean_t
441kxld_sym_is_unresolved(const KXLDSym *sym)
442{
0a7de745
A
443 return (kxld_sym_is_undefined(sym) && !kxld_sym_is_replaced(sym)) ||
444 kxld_sym_is_indirect(sym) || kxld_sym_is_common(sym);
b0d623f7
A
445}
446
447/*******************************************************************************
448*******************************************************************************/
449boolean_t
450kxld_sym_is_obsolete(const KXLDSym *sym)
451{
0a7de745 452 return 0 != sym->is_obsolete;
b0d623f7
A
453}
454
455#if KXLD_USER_OR_GOT
456/*******************************************************************************
457*******************************************************************************/
458boolean_t
459kxld_sym_is_got(const KXLDSym *sym)
460{
0a7de745 461 check(sym);
b0d623f7 462
0a7de745 463 return 0 != sym->is_got;
b0d623f7
A
464}
465#endif /* KXLD_USER_OR_GOT */
466
467/*******************************************************************************
468*******************************************************************************/
469boolean_t
470kxld_sym_is_stab(const KXLDSym *sym)
471{
0a7de745 472 check(sym);
b0d623f7 473
0a7de745 474 return 0 != sym->is_stab;
b0d623f7
A
475}
476
477/*******************************************************************************
478*******************************************************************************/
479boolean_t
480kxld_sym_is_weak(const KXLDSym *sym)
481{
0a7de745 482 check(sym);
b0d623f7 483
0a7de745 484 return 0 != sym->is_weak;
b0d623f7
A
485}
486
487/*******************************************************************************
488*******************************************************************************/
489boolean_t
490kxld_sym_is_cxx(const KXLDSym *sym)
491{
0a7de745 492 check(sym);
b0d623f7 493
0a7de745 494 return 0 != sym->is_cxx;
b0d623f7
A
495}
496
497/*******************************************************************************
498*******************************************************************************/
499boolean_t
500kxld_sym_is_pure_virtual(const KXLDSym *sym)
501{
0a7de745 502 return 0 != sym->is_pure_virtual;
b0d623f7
A
503}
504
505/*******************************************************************************
506*******************************************************************************/
507boolean_t
508kxld_sym_is_vtable(const KXLDSym *sym)
509{
0a7de745 510 check(sym);
b0d623f7 511
0a7de745 512 return kxld_sym_is_class_vtable(sym) || kxld_sym_is_metaclass_vtable(sym);
b0d623f7
A
513}
514
515/*******************************************************************************
516*******************************************************************************/
517boolean_t
518kxld_sym_is_class_vtable(const KXLDSym *sym)
519{
0a7de745 520 check(sym);
b0d623f7 521
0a7de745 522 return 0 != sym->is_class_vtable;
b0d623f7
A
523}
524
525/*******************************************************************************
526*******************************************************************************/
527boolean_t
528kxld_sym_is_metaclass_vtable(const KXLDSym *sym)
529{
0a7de745 530 check(sym);
b0d623f7 531
0a7de745 532 return 0 != sym->is_meta_vtable;
b0d623f7
A
533}
534
535/*******************************************************************************
536*******************************************************************************/
537boolean_t
538kxld_sym_is_padslot(const KXLDSym *sym)
539{
0a7de745 540 check(sym);
b0d623f7 541
0a7de745 542 return 0 != sym->is_padslot;
b0d623f7
A
543}
544
545/*******************************************************************************
546*******************************************************************************/
547boolean_t
548kxld_sym_is_metaclass(const KXLDSym *sym)
549{
0a7de745 550 check(sym);
b0d623f7 551
0a7de745 552 return 0 != sym->is_metaclass;
b0d623f7
A
553}
554
555/*******************************************************************************
556*******************************************************************************/
557boolean_t
558kxld_sym_is_super_metaclass_pointer(const KXLDSym *sym)
559{
0a7de745 560 check(sym);
b0d623f7 561
0a7de745 562 return 0 != sym->is_super_metaclass_pointer;
6d2010ae
A
563}
564
565/*******************************************************************************
566*******************************************************************************/
567boolean_t
568kxld_sym_name_is_pure_virtual(const char *name)
569{
0a7de745 570 return streq_safe(CXX_PURE_VIRTUAL, name, sizeof(CXX_PURE_VIRTUAL));
b0d623f7
A
571}
572
573/*******************************************************************************
574*******************************************************************************/
575boolean_t
576kxld_sym_name_is_padslot(const char *name)
577{
0a7de745 578 check(name);
b0d623f7 579
f427ee49 580 return strnstr(name, RESERVED_TOKEN, strlen(name)) != 0;
b0d623f7
A
581}
582
583/*******************************************************************************
584*******************************************************************************/
585u_int
586kxld_sym_get_section_offset(const KXLDSym *sym, const KXLDSect *sect)
587{
0a7de745 588 check(sym);
b0d623f7 589
0a7de745 590 return (u_int) (sym->base_addr - sect->base_addr);
b0d623f7
A
591}
592
593#if KXLD_USER_OR_COMMON
594/*******************************************************************************
595*******************************************************************************/
596kxld_size_t
597kxld_sym_get_common_size(const KXLDSym *sym)
598{
0a7de745 599 return sym->base_addr;
b0d623f7
A
600}
601
602/*******************************************************************************
603*******************************************************************************/
604u_int
605kxld_sym_get_common_align(const KXLDSym *sym)
606{
0a7de745
A
607 u_int align = GET_COMM_ALIGN(sym->desc);
608 if (!align) {
609 align = 3;
610 }
b0d623f7 611
0a7de745 612 return align;
b0d623f7
A
613}
614#endif /* KXLD_USER_OR_COMMON */
615
616/*******************************************************************************
617*******************************************************************************/
618kern_return_t
619kxld_sym_get_class_name_from_metaclass(const KXLDSym *sym,
620 char class_name[], u_long class_name_len)
621{
0a7de745 622 kern_return_t rval = KERN_FAILURE;
b0d623f7 623
0a7de745
A
624 check(sym);
625 require_action(kxld_sym_is_metaclass(sym), finish, rval = KERN_FAILURE);
b0d623f7 626
0a7de745
A
627 rval = extract_inner_string(sym->name, OSOBJ_PREFIX, METACLASS_TOKEN,
628 class_name, class_name_len);
629 require_noerr(rval, finish);
b0d623f7 630
0a7de745 631 rval = KERN_SUCCESS;
b0d623f7 632finish:
0a7de745 633 return rval;
b0d623f7
A
634}
635
636/*******************************************************************************
637*******************************************************************************/
638kern_return_t
639kxld_sym_get_class_name_from_super_metaclass_pointer(const KXLDSym *sym,
640 char class_name[], u_long class_name_len)
641{
0a7de745 642 kern_return_t rval = KERN_FAILURE;
b0d623f7 643
0a7de745
A
644 check(sym);
645 require_action(kxld_sym_is_super_metaclass_pointer(sym), finish,
646 rval = KERN_FAILURE);
b0d623f7 647
0a7de745
A
648 rval = extract_inner_string(sym->name, OSOBJ_PREFIX,
649 SUPER_METACLASS_POINTER_TOKEN, class_name, class_name_len);
650 require_noerr(rval, finish);
b0d623f7 651
0a7de745 652 rval = KERN_SUCCESS;
b0d623f7 653finish:
0a7de745 654 return rval;
b0d623f7
A
655}
656
657/*******************************************************************************
658*******************************************************************************/
659kern_return_t
660kxld_sym_get_class_name_from_vtable(const KXLDSym *sym,
661 char class_name[], u_long class_name_len)
662{
0a7de745
A
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);
b0d623f7 671
0a7de745 672 rval = KERN_SUCCESS;
b0d623f7
A
673
674finish:
0a7de745 675 return rval;
b0d623f7
A
676}
677
678/*******************************************************************************
679*******************************************************************************/
0a7de745 680kern_return_t
b0d623f7
A
681kxld_sym_get_class_name_from_vtable_name(const char *vtable_name,
682 char class_name[], u_long class_name_len)
683{
0a7de745 684 kern_return_t rval = KERN_FAILURE;
b0d623f7 685
0a7de745 686 check(vtable_name);
b0d623f7 687
0a7de745
A
688 rval = extract_inner_string(vtable_name, VTABLE_PREFIX, NULL,
689 class_name, class_name_len);
690 require_noerr(rval, finish);
b0d623f7 691
0a7de745 692 rval = KERN_SUCCESS;
b0d623f7 693finish:
0a7de745 694 return rval;
b0d623f7
A
695}
696
697/*******************************************************************************
698*******************************************************************************/
699kern_return_t
0a7de745 700kxld_sym_get_vtable_name_from_class_name(const char *class_name,
b0d623f7
A
701 char vtable_name[], u_long vtable_name_len)
702{
0a7de745
A
703 kern_return_t rval = KERN_FAILURE;
704 u_long outlen = 0;
b0d623f7 705
0a7de745
A
706 check(class_name);
707 check(vtable_name);
b0d623f7 708
0a7de745
A
709 outlen = strlcpy(vtable_name, VTABLE_PREFIX, vtable_name_len);
710 require_action(outlen < vtable_name_len, finish,
711 rval = KERN_FAILURE);
b0d623f7 712
0a7de745
A
713 outlen = strlcat(vtable_name, class_name, vtable_name_len);
714 require_action(outlen < vtable_name_len, finish,
715 rval = KERN_FAILURE);
b0d623f7 716
0a7de745 717 rval = KERN_SUCCESS;
b0d623f7 718finish:
0a7de745 719 return rval;
b0d623f7
A
720}
721
722/*******************************************************************************
723*******************************************************************************/
724kern_return_t
0a7de745 725kxld_sym_get_meta_vtable_name_from_class_name(const char *class_name,
b0d623f7
A
726 char meta_vtable_name[], u_long meta_vtable_name_len)
727{
0a7de745
A
728 kern_return_t rval = KERN_FAILURE;
729 u_long outlen = 0;
b0d623f7 730
0a7de745
A
731 check(class_name);
732 check(meta_vtable_name);
b0d623f7 733
0a7de745
A
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);
b0d623f7 738
0a7de745
A
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);
b0d623f7 742
0a7de745
A
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);
b0d623f7 747
0a7de745 748 rval = KERN_SUCCESS;
b0d623f7 749finish:
0a7de745 750 return rval;
b0d623f7
A
751}
752
753/*******************************************************************************
754*******************************************************************************/
755kern_return_t
0a7de745 756kxld_sym_get_final_sym_name_from_class_name(const char *class_name,
b0d623f7
A
757 char final_sym_name[], u_long final_sym_name_len)
758{
0a7de745
A
759 kern_return_t rval = KERN_FAILURE;
760 u_long outlen = 0;
b0d623f7 761
0a7de745
A
762 check(class_name);
763 check(final_sym_name);
b0d623f7 764
0a7de745
A
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);
b0d623f7 768
0a7de745
A
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);
b0d623f7 772
0a7de745
A
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);
b0d623f7 776
0a7de745 777 rval = KERN_SUCCESS;
b0d623f7
A
778
779finish:
0a7de745 780 return rval;
b0d623f7
A
781}
782
783/*******************************************************************************
784*******************************************************************************/
785u_long
786kxld_sym_get_function_prefix_from_class_name(const char *class_name,
787 char function_prefix[], u_long function_prefix_len)
788{
0a7de745
A
789 u_long rval = 0;
790 u_long outlen = 0;
b0d623f7 791
0a7de745
A
792 check(class_name);
793 check(function_prefix);
b0d623f7 794
0a7de745
A
795 outlen = strlcpy(function_prefix, OSOBJ_PREFIX, function_prefix_len);
796 require(outlen < function_prefix_len, finish);
b0d623f7 797
0a7de745
A
798 outlen = strlcat(function_prefix, class_name, function_prefix_len);
799 require(outlen < function_prefix_len, finish);
b0d623f7 800
0a7de745 801 rval = outlen;
b0d623f7 802finish:
0a7de745 803 return rval;
b0d623f7
A
804}
805
806/*******************************************************************************
807*******************************************************************************/
808static kern_return_t
0a7de745 809extract_inner_string(const char *str, const char *prefix, const char *suffix,
b0d623f7
A
810 char *buf, u_long len)
811{
0a7de745
A
812 kern_return_t rval = KERN_FAILURE;
813 u_long prelen = 0, suflen = 0, striplen = 0;
b0d623f7 814
0a7de745
A
815 check(str);
816 check(buf);
b0d623f7 817
0a7de745
A
818 prelen = (prefix) ? strlen(prefix) : 0;
819 suflen = (suffix) ? strlen(suffix) : 0;
820 striplen = strlen(str) - prelen - suflen;
b0d623f7 821
0a7de745 822 require_action(striplen < len, finish, rval = KERN_FAILURE);
b0d623f7 823
0a7de745
A
824 strncpy(buf, str + prelen, striplen);
825 buf[striplen] = '\0';
b0d623f7 826
0a7de745 827 rval = KERN_SUCCESS;
b0d623f7 828finish:
0a7de745 829 return rval;
b0d623f7
A
830}
831
832#if KXLD_USER_OR_GOT
833/*******************************************************************************
834*******************************************************************************/
835void
836kxld_sym_set_got(KXLDSym *sym)
837{
0a7de745 838 sym->is_got = 1;
b0d623f7
A
839}
840#endif /* KXLD_USER_OR_GOT */
841
842/*******************************************************************************
843*******************************************************************************/
844void
845kxld_sym_relocate(KXLDSym *sym, const KXLDSect *sect)
846{
0a7de745
A
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 }
b0d623f7
A
851}
852
853#if KXLD_USER_OR_ILP32
854/*******************************************************************************
855*******************************************************************************/
856kern_return_t
0a7de745 857kxld_sym_export_macho_32(const KXLDSym *sym, u_char *_nl, char *strtab,
6d2010ae 858 u_long *stroff, u_long strsize)
b0d623f7 859{
0a7de745
A
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;
b0d623f7
A
888
889finish:
0a7de745 890 return rval;
b0d623f7
A
891}
892#endif /* KXLD_USER_OR_ILP32 */
893
894#if KXLD_USER_OR_LP64
895/*******************************************************************************
896*******************************************************************************/
897kern_return_t
898kxld_sym_export_macho_64(const KXLDSym *sym, u_char *_nl, char *strtab,
6d2010ae 899 u_long *stroff, u_long strsize)
b0d623f7 900{
0a7de745
A
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;
b0d623f7 905
0a7de745
A
906 check(sym);
907 check(nl);
908 check(strtab);
909 check(stroff);
b0d623f7 910
0a7de745
A
911 bytes = strlen(sym->name) + 1;
912 require_action((u_long)bytes <= strsize - *stroff, finish,
913 rval = KERN_FAILURE);
b0d623f7 914
0a7de745
A
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 }
b0d623f7 923
0a7de745 924 str = (char *) (strtab + *stroff);
39037602 925
0a7de745 926 strlcpy(str, sym->name, strsize - *stroff);
b0d623f7 927
0a7de745 928 *stroff += bytes;
39037602 929
0a7de745 930 rval = KERN_SUCCESS;
b0d623f7
A
931
932finish:
0a7de745 933 return rval;
b0d623f7
A
934}
935#endif /* KXLD_USER_OR_LP64 */
936
937/*******************************************************************************
938*******************************************************************************/
939kern_return_t
0a7de745 940kxld_sym_resolve(KXLDSym *sym, kxld_addr_t addr)
b0d623f7 941{
0a7de745
A
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);
b0d623f7 948
0a7de745 949 /* Set the n_list data types */
b0d623f7 950
0a7de745
A
951 sym->link_addr = addr;
952 sym->type = N_ABS | N_EXT;
953 sym->sectnum = NO_SECT;
b0d623f7 954
0a7de745 955 /* Set the predicate bits for an externally resolved symbol. */
b0d623f7 956
0a7de745
A
957 sym->is_external = TRUE;
958 sym->is_absolute = TRUE;
959 sym->is_resolved = TRUE;
6d2010ae 960
0a7de745 961 /* Clear the predicate bits for types that can be resolved */
b0d623f7 962
0a7de745
A
963 sym->is_undefined = FALSE;
964 sym->is_indirect = FALSE;
b0d623f7 965
0a7de745 966 rval = KERN_SUCCESS;
b0d623f7
A
967
968finish:
969
0a7de745 970 return rval;
b0d623f7
A
971}
972
973#if KXLD_USER_OR_COMMON
974/*******************************************************************************
975*******************************************************************************/
976kern_return_t
977kxld_sym_resolve_common(KXLDSym *sym, u_int sectnum, kxld_addr_t base_addr)
978{
0a7de745 979 kern_return_t rval = KERN_FAILURE;
b0d623f7 980
0a7de745 981 check(sym);
b0d623f7 982
0a7de745
A
983 require_action(kxld_sym_is_common(sym), finish,
984 rval = KERN_FAILURE);
b0d623f7 985
0a7de745
A
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;
b0d623f7 991
0a7de745
A
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;
b0d623f7 998
0a7de745 999 rval = KERN_SUCCESS;
b0d623f7
A
1000
1001finish:
1002
0a7de745 1003 return rval;
b0d623f7
A
1004}
1005#endif /* KXLD_USER_OR_COMMON */
1006
1007/*******************************************************************************
1008*******************************************************************************/
1009void
1010kxld_sym_delete(KXLDSym *sym)
1011{
0a7de745 1012 check(sym);
b0d623f7 1013
0a7de745
A
1014 bzero(sym, sizeof(*sym));
1015 sym->is_replaced = TRUE;
b0d623f7
A
1016}
1017
1018
1019/*******************************************************************************
1020*******************************************************************************/
1021void
1022kxld_sym_patch(KXLDSym *sym)
1023{
0a7de745 1024 check(sym);
b0d623f7 1025
0a7de745 1026 sym->is_replaced = TRUE;
b0d623f7
A
1027}
1028
1029/*******************************************************************************
1030*******************************************************************************/
1031void
1032kxld_sym_mark_private(KXLDSym *sym)
1033{
0a7de745 1034 check(sym);
b0d623f7 1035
0a7de745
A
1036 sym->type |= N_PEXT;
1037 sym->is_external = FALSE;
b0d623f7 1038}