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