]> git.saurik.com Git - apple/xnu.git/blob - libkern/kxld/kxld_sect.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_sect.c
1 /*
2 * Copyright (c) 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 #include <string.h>
29 #include <mach-o/loader.h>
30 #include <mach-o/reloc.h>
31 #include <sys/types.h>
32
33 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "kxld"
34 #include <AssertMacros.h>
35
36 #include "kxld_reloc.h"
37 #include "kxld_sect.h"
38 #include "kxld_seg.h"
39 #include "kxld_symtab.h"
40 #include "kxld_util.h"
41
42 static kern_return_t export_macho(const KXLDSect *sect, u_char *buf, u_long offset,
43 u_long bufsize);
44 #if KXLD_USER_OR_ILP32
45 static kern_return_t sect_export_macho_header_32(const KXLDSect *sect, u_char *buf,
46 u_long *header_offset, u_long header_size, u_long data_offset);
47 #endif
48 #if KXLD_USER_OR_LP64
49 static kern_return_t sect_export_macho_header_64(const KXLDSect *sect, u_char *buf,
50 u_long *header_offset, u_long header_size, u_long data_offset);
51 #endif
52 extern boolean_t isSplitKext;
53
54 #if KXLD_USER_OR_ILP32
55 /*******************************************************************************
56 *******************************************************************************/
57 kern_return_t
58 kxld_sect_init_from_macho_32(KXLDSect *sect, u_char *macho, u_long *sect_offset,
59 u_int sectnum, const KXLDRelocator *relocator)
60 {
61 kern_return_t rval = KERN_FAILURE;
62 struct section *src = (struct section *) ((void *) (macho + *sect_offset));
63 struct relocation_info *relocs = NULL;
64
65 check(sect);
66 check(macho);
67 check(src);
68
69 strlcpy(sect->segname, src->segname, sizeof(sect->segname));
70 strlcpy(sect->sectname, src->sectname, sizeof(sect->sectname));
71 sect->base_addr = src->addr;
72 sect->link_addr = src->addr;
73 sect->size = src->size;
74 sect->sectnum = sectnum;
75 sect->flags = src->flags;
76 sect->align = src->align;
77 sect->reserved1 = src->reserved1;
78 sect->reserved2 = src->reserved2;
79
80 if (src->offset) {
81 sect->data = macho + src->offset;
82 } else {
83 sect->data = NULL;
84 }
85
86 relocs = (struct relocation_info *) ((void *) (macho + src->reloff));
87
88 rval = kxld_reloc_create_macho(&sect->relocs, relocator,
89 relocs, src->nreloc);
90 require_noerr(rval, finish);
91
92 *sect_offset += sizeof(*src);
93 rval = KERN_SUCCESS;
94
95 finish:
96 if (rval) {
97 kxld_sect_deinit(sect);
98 }
99
100 return rval;
101 }
102 #endif /* KXLD_USER_OR_ILP32 */
103
104 #if KXLD_USER_OR_LP64
105 /*******************************************************************************
106 *******************************************************************************/
107 kern_return_t
108 kxld_sect_init_from_macho_64(KXLDSect *sect, u_char *macho, u_long *sect_offset,
109 u_int sectnum, const KXLDRelocator *relocator)
110 {
111 kern_return_t rval = KERN_FAILURE;
112 struct section_64 *src = (struct section_64 *) ((void *) (macho + *sect_offset));
113 struct relocation_info *relocs = NULL;
114
115 check(sect);
116 check(macho);
117 check(src);
118
119 strlcpy(sect->segname, src->segname, sizeof(sect->segname));
120 strlcpy(sect->sectname, src->sectname, sizeof(sect->sectname));
121 sect->base_addr = src->addr;
122 sect->link_addr = src->addr;
123 sect->size = src->size;
124 sect->sectnum = sectnum;
125 sect->flags = src->flags;
126 sect->align = src->align;
127 sect->reserved1 = src->reserved1;
128 sect->reserved2 = src->reserved2;
129
130 if (src->offset) {
131 sect->data = macho + src->offset;
132 } else {
133 sect->data = NULL;
134 }
135
136 relocs = (struct relocation_info *) ((void *) (macho + src->reloff));
137
138 rval = kxld_reloc_create_macho(&sect->relocs, relocator,
139 relocs, src->nreloc);
140 require_noerr(rval, finish);
141
142 *sect_offset += sizeof(*src);
143 rval = KERN_SUCCESS;
144
145 finish:
146 if (rval) {
147 kxld_sect_deinit(sect);
148 }
149
150 return rval;
151 }
152 #endif /* KXLD_USER_OR_LP64 */
153
154 #if KXLD_USER_OR_GOT
155 /*******************************************************************************
156 * Assumes GOT is comprised of kxld_addr_t entries
157 *******************************************************************************/
158 kern_return_t
159 kxld_sect_init_got(KXLDSect *sect, u_int ngots)
160 {
161 kern_return_t rval = KERN_FAILURE;
162
163 check(sect);
164
165 strlcpy(sect->segname, KXLD_SEG_GOT, sizeof(sect->segname));
166 strlcpy(sect->sectname, KXLD_SECT_GOT, sizeof(sect->sectname));
167 sect->base_addr = 0;
168 sect->link_addr = 0;
169 sect->flags = 0;
170 sect->align = 4;
171 sect->reserved1 = 0;
172 sect->reserved2 = 0;
173
174 sect->size = ngots * sizeof(kxld_addr_t);
175 sect->data = kxld_alloc((u_long) sect->size);
176 require_action(sect->data, finish, rval = KERN_RESOURCE_SHORTAGE);
177
178 sect->allocated = TRUE;
179
180 rval = KERN_SUCCESS;
181
182 finish:
183 return rval;
184 }
185 #endif /* KXLD_USER_OR_GOT */
186
187 #if KXLD_USER_OR_COMMON
188 /*******************************************************************************
189 *******************************************************************************/
190 void
191 kxld_sect_init_zerofill(KXLDSect *sect, const char *segname,
192 const char *sectname, kxld_size_t size, u_int align)
193 {
194 check(sect);
195 check(segname);
196 check(sectname);
197
198 strlcpy(sect->segname, segname, sizeof(sect->segname));
199 strlcpy(sect->sectname, sectname, sizeof(sect->sectname));
200 sect->size = size;
201 sect->align = align;
202 sect->base_addr = 0;
203 sect->link_addr = 0;
204 sect->flags = S_ZEROFILL;
205 }
206 #endif /* KXLD_USER_OR_COMMON */
207
208 /*******************************************************************************
209 *******************************************************************************/
210 void
211 kxld_sect_clear(KXLDSect *sect)
212 {
213 check(sect);
214
215 if (sect->allocated) {
216 kxld_free(sect->data, (u_long) sect->size);
217 sect->allocated = FALSE;
218 }
219
220 bzero(sect->sectname, sizeof(sect->sectname));
221 bzero(sect->segname, sizeof(sect->segname));
222 sect->data = NULL;
223 sect->base_addr = 0;
224 sect->link_addr = 0;
225 sect->size = 0;
226 sect->flags = 0;
227 sect->align = 0;
228 sect->reserved1 = 0;
229 sect->reserved2 = 0;
230 kxld_array_clear(&sect->relocs);
231 }
232
233 /*******************************************************************************
234 *******************************************************************************/
235 void
236 kxld_sect_deinit(KXLDSect *sect)
237 {
238 check(sect);
239
240 if (streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT))) {
241 kxld_free(sect->data, (u_long) sect->size);
242 }
243
244 kxld_array_deinit(&sect->relocs);
245 bzero(sect, sizeof(*sect));
246 }
247
248 /*******************************************************************************
249 *******************************************************************************/
250 u_int
251 kxld_sect_get_num_relocs(const KXLDSect *sect)
252 {
253 check(sect);
254
255 return sect->relocs.nitems;
256 }
257
258 /*******************************************************************************
259 *******************************************************************************/
260 u_long
261 kxld_sect_get_macho_header_size(boolean_t is_32_bit)
262 {
263 if (is_32_bit) {
264 return sizeof(struct section);
265 } else {
266 return sizeof(struct section_64);
267 }
268 }
269
270 /*******************************************************************************
271 *******************************************************************************/
272 u_long
273 kxld_sect_get_macho_data_size(const KXLDSect *sect)
274 {
275 u_long size = 0;
276
277 check(sect);
278
279 if (sect->data) {
280 size = (u_long) sect->size;
281 }
282
283 return size;
284 }
285
286 #if KXLD_USER_OR_GOT
287 /*******************************************************************************
288 *******************************************************************************/
289 u_int
290 kxld_sect_get_ngots(const KXLDSect *sect, const KXLDRelocator *relocator,
291 const KXLDSymtab *symtab)
292 {
293 const KXLDReloc *reloc = NULL;
294 KXLDSym *sym = NULL;
295 u_int ngots = 0;
296 u_int i = 0;
297
298 for (i = 0; i < sect->relocs.nitems; ++i) {
299 reloc = kxld_array_get_item(&sect->relocs, i);
300
301 if (relocator->reloc_has_got(reloc->reloc_type)) {
302 /* @TODO This assumes 64-bit symbols (which is valid at the
303 * moment since only x86_64 has a GOT)
304 */
305 sym = kxld_reloc_get_symbol(relocator, reloc, sect->data, symtab);
306 if (!kxld_sym_is_got(sym)) {
307 kxld_sym_set_got(sym);
308 ++ngots;
309 }
310 }
311 }
312
313 return ngots;
314 }
315 #endif /* KXLD_USER_OR_GOT */
316
317 /*******************************************************************************
318 * Each section must be aligned at a certain power of two. To figure out that
319 * alignment, we mask for the low bits that may need to be adjusted. If they are
320 * non zero, we then subtract them from the target alignment to find the offset,
321 * and then add that offset to the link address.
322 *******************************************************************************/
323 kxld_addr_t
324 kxld_sect_align_address(const KXLDSect *sect, kxld_addr_t address)
325 {
326 return kxld_align_address(address, sect->align);
327 }
328
329 /*******************************************************************************
330 *******************************************************************************/
331 kern_return_t
332 kxld_sect_export_macho_to_file_buffer(const KXLDSect *sect, u_char *buf,
333 u_long *header_offset, u_long header_size, u_long *data_offset,
334 u_long data_size, boolean_t is_32_bit __unused)
335 {
336 kern_return_t rval = KERN_FAILURE;
337
338 check(sect);
339 check(buf);
340 check(header_offset);
341 check(data_offset);
342
343 /* If there is no data to export, we only need to write the header. We
344 * make it a separate call so that we don't modify data_offset.
345 */
346 if (!sect->data) {
347 KXLD_3264_FUNC(is_32_bit, rval,
348 sect_export_macho_header_32, sect_export_macho_header_64,
349 sect, buf, header_offset, header_size, /* data_offset */ 0);
350 require_noerr(rval, finish);
351 } else {
352 *data_offset = (u_long) kxld_sect_align_address(sect, *data_offset);
353
354 KXLD_3264_FUNC(is_32_bit, rval,
355 sect_export_macho_header_32, sect_export_macho_header_64,
356 sect, buf, header_offset, header_size, *data_offset);
357 require_noerr(rval, finish);
358
359 rval = export_macho(sect, buf, *data_offset, data_size);
360 require_noerr(rval, finish);
361
362 *data_offset += (u_long) sect->size;
363 }
364 rval = KERN_SUCCESS;
365
366 finish:
367 return rval;
368 }
369
370 /*******************************************************************************
371 *******************************************************************************/
372 kern_return_t
373 kxld_sect_export_macho_to_vm(const KXLDSect *sect,
374 u_char *buf,
375 u_long *header_offset,
376 u_long header_size,
377 kxld_addr_t link_addr,
378 u_long data_size,
379 boolean_t is_32_bit __unused)
380 {
381 kern_return_t rval = KERN_FAILURE;
382 u_long data_offset;
383
384 check(sect);
385 check(buf);
386 check(header_offset);
387
388 data_offset = (u_long) (sect->link_addr - link_addr);
389
390 KXLD_3264_FUNC(is_32_bit, rval,
391 sect_export_macho_header_32, sect_export_macho_header_64,
392 sect, buf, header_offset, header_size, data_offset);
393 require_noerr(rval, finish);
394
395 rval = export_macho(sect, buf, data_offset, data_size);
396 require_noerr(rval, finish);
397
398 rval = KERN_SUCCESS;
399
400 finish:
401 return rval;
402 }
403
404 /*******************************************************************************
405 *******************************************************************************/
406 static kern_return_t
407 export_macho(const KXLDSect *sect, u_char *buf, u_long offset, u_long bufsize)
408 {
409 kern_return_t rval = KERN_FAILURE;
410
411 check(sect);
412 check(buf);
413
414 if (!sect->data) {
415 rval = KERN_SUCCESS;
416 goto finish;
417 }
418
419 if (!isSplitKext) {
420 /* Verify that the section is properly aligned */
421 if (kxld_sect_align_address(sect, offset) != offset) {
422 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
423 "Alignment error: %llu != %lu for %s %s <%s>",
424 kxld_sect_align_address(sect, offset), offset,
425 sect->segname, sect->sectname, __func__);
426 goto finish;
427 }
428 }
429
430 /* Verify that we have enough space to copy */
431 if (buf + offset + sect->size > buf + bufsize) {
432 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
433 "Overflow: offset %lu + sect->size %llu > bufsize %lu for %s %s",
434 offset, sect->size, bufsize,
435 sect->segname, sect->sectname);
436 goto finish;
437 }
438
439 /* Copy section data */
440 switch (sect->flags & SECTION_TYPE) {
441 case S_NON_LAZY_SYMBOL_POINTERS:
442 case S_MOD_INIT_FUNC_POINTERS:
443 case S_MOD_TERM_FUNC_POINTERS:
444 case S_REGULAR:
445 case S_CSTRING_LITERALS:
446 case S_4BYTE_LITERALS:
447 case S_8BYTE_LITERALS:
448 case S_LITERAL_POINTERS:
449 case S_COALESCED:
450 case S_16BYTE_LITERALS:
451 case S_SYMBOL_STUBS:
452 #if SPLIT_KEXTS_DEBUG
453 kxld_log(kKxldLogLinking, kKxldLogErr,
454 " sectname %s copy from %p (sect->data) for %llu bytes (sect->size) to %p (buf %p + offset %lu <%s>",
455 sect->sectname[0] ? sect->sectname : "none",
456 (void *) sect->data,
457 sect->size,
458 (void *) (buf + offset),
459 (void *) buf,
460 offset,
461 __func__);
462
463 kxld_log(kKxldLogLinking, kKxldLogErr,
464 " %p >>> Start of %s section data (sect->size %llu) <%s>",
465 (void *) (buf + offset),
466 sect->sectname[0] ? sect->sectname : "none",
467 sect->size,
468 __func__);
469 kxld_log(kKxldLogLinking, kKxldLogErr,
470 " %p <<< End of %s section data <%s>",
471 (void *) (buf + offset + sect->size),
472 sect->sectname[0] ? sect->sectname : "none",
473 __func__);
474 #endif
475 memcpy(buf + offset, sect->data, (size_t)sect->size);
476 break;
477 case S_ZEROFILL: /* sect->data should be NULL, so we'll never get here */
478 case S_LAZY_SYMBOL_POINTERS:
479 case S_GB_ZEROFILL:
480 case S_INTERPOSING:
481 case S_DTRACE_DOF:
482 default:
483 rval = KERN_FAILURE;
484 kxld_log(kKxldLogLinking, kKxldLogErr, kKxldLogMalformedMachO
485 "Invalid section type: %u.", sect->flags & SECTION_TYPE);
486 goto finish;
487 }
488
489 rval = KERN_SUCCESS;
490
491 finish:
492 return rval;
493 }
494
495 #if KXLD_USER_OR_ILP32
496 /*******************************************************************************
497 *******************************************************************************/
498 static kern_return_t
499 sect_export_macho_header_32(const KXLDSect *sect, u_char *buf,
500 u_long *header_offset, u_long header_size, u_long data_offset)
501 {
502 kern_return_t rval = KERN_FAILURE;
503 struct section *secthdr = NULL;
504
505 check(sect);
506 check(buf);
507 check(header_offset);
508
509 require_action(sizeof(*secthdr) <= header_size - *header_offset, finish,
510 rval = KERN_FAILURE);
511 secthdr = (struct section *) ((void *) (buf + *header_offset));
512 *header_offset += sizeof(*secthdr);
513
514 /* Initalize header */
515
516 strlcpy(secthdr->sectname, sect->sectname, sizeof(secthdr->sectname));
517 strlcpy(secthdr->segname, sect->segname, sizeof(secthdr->segname));
518 secthdr->addr = (uint32_t) sect->link_addr;
519 secthdr->size = (uint32_t) sect->size;
520 secthdr->offset = (uint32_t) ((sect->data) ? data_offset : 0);
521 secthdr->align = sect->align;
522 secthdr->reloff = 0;
523 secthdr->nreloc = 0;
524 secthdr->flags = sect->flags;
525 secthdr->reserved1 = sect->reserved1;
526 secthdr->reserved2 = sect->reserved2;
527
528 #if SPLIT_KEXTS_DEBUG
529 {
530 kxld_log(kKxldLogLinking, kKxldLogErr,
531 "sectname %s secthdr: %p addr %p size %02X %u offset %02X %u <%s>",
532 sect->sectname[0] ? sect->sectname : "none",
533 (void *) secthdr,
534 (void *) ((uint64_t)secthdr->addr),
535 secthdr->size,
536 secthdr->size,
537 secthdr->offset,
538 secthdr->offset,
539 __func__);
540 }
541 #endif
542
543 rval = KERN_SUCCESS;
544
545 finish:
546 return rval;
547 }
548 #endif /* KXLD_USER_OR_ILP32 */
549
550 #if KXLD_USER_OR_LP64
551 /*******************************************************************************
552 *******************************************************************************/
553 static kern_return_t
554 sect_export_macho_header_64(const KXLDSect *sect, u_char *buf,
555 u_long *header_offset, u_long header_size, u_long data_offset)
556 {
557 kern_return_t rval = KERN_FAILURE;
558 struct section_64 *secthdr = NULL;
559
560 check(sect);
561 check(buf);
562 check(header_offset);
563
564
565 require_action(sizeof(*secthdr) <= header_size - *header_offset, finish,
566 rval = KERN_FAILURE);
567 secthdr = (struct section_64 *) ((void *) (buf + *header_offset));
568 *header_offset += sizeof(*secthdr);
569
570 /* Initalize header */
571
572 strlcpy(secthdr->sectname, sect->sectname, sizeof(secthdr->sectname));
573 strlcpy(secthdr->segname, sect->segname, sizeof(secthdr->segname));
574 secthdr->addr = (uint64_t) sect->link_addr;
575 secthdr->size = (uint64_t) sect->size;
576 secthdr->offset = (uint32_t) ((sect->data) ? data_offset : 0);
577 secthdr->align = sect->align;
578 secthdr->reloff = 0;
579 secthdr->nreloc = 0;
580 secthdr->flags = sect->flags;
581 secthdr->reserved1 = sect->reserved1;
582 secthdr->reserved2 = sect->reserved2;
583
584 #if SPLIT_KEXTS_DEBUG
585 kxld_log(kKxldLogLinking, kKxldLogErr,
586 " %p >>> Start of %s secthdr (size %lu) <%s>",
587 (void *) secthdr,
588 sect->sectname[0] ? sect->sectname : "none",
589 sizeof(*secthdr),
590 __func__);
591 kxld_log(kKxldLogLinking, kKxldLogErr,
592 " %p <<< End of %s secthdr <%s>",
593 (void *) ((u_char *)secthdr + sizeof(*secthdr)),
594 sect->sectname[0] ? sect->sectname : "none",
595 __func__);
596 kxld_log(kKxldLogLinking, kKxldLogErr,
597 " secthdr: addr %p size %llu offset %u sectname %s <%s>",
598 (void *) secthdr->addr,
599 secthdr->size,
600 secthdr->offset,
601 sect->sectname[0] ? sect->sectname : "none",
602 __func__);
603 #endif
604
605 rval = KERN_SUCCESS;
606
607 finish:
608 return rval;
609 }
610 #endif /* KXLD_USER_OR_LP64 */
611
612 #if KXLD_USER_OR_COMMON
613 /*******************************************************************************
614 *******************************************************************************/
615 kxld_size_t
616 kxld_sect_grow(KXLDSect *sect, kxld_size_t nbytes, u_int align)
617 {
618 kxld_size_t size = kxld_align_address(sect->size, align);
619
620 if (align > sect->align) {
621 sect->align = align;
622 }
623 sect->size = size + nbytes;
624
625 return size;
626 }
627 #endif /* KXLD_USER_OR_COMMON */
628
629 /*******************************************************************************
630 *******************************************************************************/
631 void
632 kxld_sect_relocate(KXLDSect *sect, kxld_addr_t link_addr)
633 {
634 #if SPLIT_KEXTS_DEBUG
635 {
636 kxld_log(kKxldLogLinking, kKxldLogErr,
637 "%p >>> Start of %s section (sect->size %llu) <%s>",
638 (void *) (kxld_sect_align_address(sect, sect->link_addr + link_addr)),
639 sect->sectname[0] ? sect->sectname : "none",
640 sect->size,
641 __func__);
642 kxld_log(kKxldLogLinking, kKxldLogErr,
643 "%p <<< End of %s section <%s>",
644 (void *) (kxld_sect_align_address(sect, sect->link_addr + link_addr) + sect->size),
645 sect->sectname[0] ? sect->sectname : "none",
646 __func__);
647 }
648 #endif
649
650 sect->link_addr = kxld_sect_align_address(sect,
651 sect->link_addr + link_addr);
652 }
653
654 #if KXLD_USER_OR_GOT
655 /*******************************************************************************
656 *******************************************************************************/
657 kern_return_t
658 kxld_sect_populate_got(KXLDSect *sect, KXLDSymtab *symtab,
659 boolean_t swap __unused)
660 {
661 kern_return_t rval = KERN_FAILURE;
662 KXLDSymtabIterator iter;
663 KXLDSym *sym = NULL;
664 kxld_addr_t *entry = NULL;
665 kxld_addr_t entry_addr = 0;
666
667 check(sect);
668 check(symtab);
669 require(streq_safe(sect->segname, KXLD_SEG_GOT, sizeof(KXLD_SEG_GOT)),
670 finish);
671 require(streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT)),
672 finish);
673
674 kxld_symtab_iterator_init(&iter, symtab, kxld_sym_is_got, FALSE);
675
676 entry = (kxld_addr_t *) sect->data;
677 entry_addr = sect->link_addr;
678 while ((sym = kxld_symtab_iterator_get_next(&iter))) {
679 *entry = sym->link_addr;
680 sym->got_addr = entry_addr;
681
682 #if !KERNEL
683 if (swap) {
684 *entry = OSSwapInt64(*entry);
685 }
686 #endif /* !KERNEL */
687
688 ++entry;
689 entry_addr += sizeof(*entry);
690 }
691
692 rval = KERN_SUCCESS;
693
694 finish:
695 return rval;
696 }
697 #endif /* KXLD_USER_OR_GOT */
698
699 /*******************************************************************************
700 *******************************************************************************/
701 kern_return_t
702 kxld_sect_process_relocs(KXLDSect *sect, KXLDRelocator *relocator)
703 {
704 kern_return_t rval = KERN_FAILURE;
705 KXLDReloc *reloc = NULL;
706 u_int i = 0;
707
708 for (i = 0; i < sect->relocs.nitems; ++i) {
709 reloc = kxld_array_get_item(&sect->relocs, i);
710 rval = kxld_relocator_process_sect_reloc(relocator, reloc, sect);
711 require_noerr(rval, finish);
712 }
713
714 rval = KERN_SUCCESS;
715 finish:
716 return rval;
717 }