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