]> git.saurik.com Git - apple/xnu.git/blame - libkern/kxld/kxld_sect.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libkern / kxld / kxld_sect.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 <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
0a7de745 42static kern_return_t export_macho(const KXLDSect *sect, u_char *buf, u_long offset,
6d2010ae 43 u_long bufsize);
b0d623f7 44#if KXLD_USER_OR_ILP32
0a7de745 45static kern_return_t sect_export_macho_header_32(const KXLDSect *sect, u_char *buf,
b0d623f7
A
46 u_long *header_offset, u_long header_size, u_long data_offset);
47#endif
48#if KXLD_USER_OR_LP64
0a7de745 49static kern_return_t sect_export_macho_header_64(const KXLDSect *sect, u_char *buf,
b0d623f7
A
50 u_long *header_offset, u_long header_size, u_long data_offset);
51#endif
39037602 52extern boolean_t isSplitKext;
b0d623f7
A
53
54#if KXLD_USER_OR_ILP32
55/*******************************************************************************
56*******************************************************************************/
57kern_return_t
58kxld_sect_init_from_macho_32(KXLDSect *sect, u_char *macho, u_long *sect_offset,
59 u_int sectnum, const KXLDRelocator *relocator)
60{
0a7de745
A
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;
b0d623f7
A
94
95finish:
0a7de745
A
96 if (rval) {
97 kxld_sect_deinit(sect);
98 }
b0d623f7 99
0a7de745 100 return rval;
b0d623f7
A
101}
102#endif /* KXLD_USER_OR_ILP32 */
103
104#if KXLD_USER_OR_LP64
105/*******************************************************************************
106*******************************************************************************/
107kern_return_t
108kxld_sect_init_from_macho_64(KXLDSect *sect, u_char *macho, u_long *sect_offset,
109 u_int sectnum, const KXLDRelocator *relocator)
110{
0a7de745
A
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;
b0d623f7
A
144
145finish:
0a7de745
A
146 if (rval) {
147 kxld_sect_deinit(sect);
148 }
b0d623f7 149
0a7de745 150 return rval;
b0d623f7
A
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*******************************************************************************/
158kern_return_t
159kxld_sect_init_got(KXLDSect *sect, u_int ngots)
160{
0a7de745 161 kern_return_t rval = KERN_FAILURE;
b0d623f7 162
0a7de745 163 check(sect);
b0d623f7 164
0a7de745
A
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;
b0d623f7 173
0a7de745
A
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);
b0d623f7 177
0a7de745 178 sect->allocated = TRUE;
b0d623f7 179
0a7de745 180 rval = KERN_SUCCESS;
b0d623f7
A
181
182finish:
0a7de745 183 return rval;
b0d623f7
A
184}
185#endif /* KXLD_USER_OR_GOT */
186
187#if KXLD_USER_OR_COMMON
188/*******************************************************************************
189*******************************************************************************/
190void
0a7de745 191kxld_sect_init_zerofill(KXLDSect *sect, const char *segname,
b0d623f7
A
192 const char *sectname, kxld_size_t size, u_int align)
193{
0a7de745
A
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;
b0d623f7
A
205}
206#endif /* KXLD_USER_OR_COMMON */
207
208/*******************************************************************************
209*******************************************************************************/
210void
211kxld_sect_clear(KXLDSect *sect)
212{
0a7de745
A
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);
b0d623f7
A
231}
232
233/*******************************************************************************
234*******************************************************************************/
235void
236kxld_sect_deinit(KXLDSect *sect)
237{
0a7de745 238 check(sect);
b0d623f7 239
0a7de745
A
240 if (streq_safe(sect->sectname, KXLD_SECT_GOT, sizeof(KXLD_SECT_GOT))) {
241 kxld_free(sect->data, (u_long) sect->size);
242 }
b0d623f7 243
0a7de745
A
244 kxld_array_deinit(&sect->relocs);
245 bzero(sect, sizeof(*sect));
b0d623f7
A
246}
247
248/*******************************************************************************
249*******************************************************************************/
0a7de745 250u_int
b0d623f7
A
251kxld_sect_get_num_relocs(const KXLDSect *sect)
252{
0a7de745 253 check(sect);
b0d623f7 254
0a7de745 255 return sect->relocs.nitems;
b0d623f7
A
256}
257
258/*******************************************************************************
259*******************************************************************************/
260u_long
261kxld_sect_get_macho_header_size(boolean_t is_32_bit)
262{
0a7de745
A
263 if (is_32_bit) {
264 return sizeof(struct section);
265 } else {
266 return sizeof(struct section_64);
267 }
b0d623f7
A
268}
269
270/*******************************************************************************
271*******************************************************************************/
272u_long
273kxld_sect_get_macho_data_size(const KXLDSect *sect)
274{
0a7de745 275 u_long size = 0;
b0d623f7 276
0a7de745 277 check(sect);
b0d623f7 278
0a7de745
A
279 if (sect->data) {
280 size = (u_long) sect->size;
281 }
b0d623f7 282
0a7de745 283 return size;
b0d623f7
A
284}
285
286#if KXLD_USER_OR_GOT
287/*******************************************************************************
288*******************************************************************************/
289u_int
290kxld_sect_get_ngots(const KXLDSect *sect, const KXLDRelocator *relocator,
291 const KXLDSymtab *symtab)
292{
0a7de745
A
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;
b0d623f7
A
314}
315#endif /* KXLD_USER_OR_GOT */
316
317/*******************************************************************************
0a7de745
A
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,
b0d623f7
A
321* and then add that offset to the link address.
322*******************************************************************************/
323kxld_addr_t
324kxld_sect_align_address(const KXLDSect *sect, kxld_addr_t address)
325{
0a7de745 326 return kxld_align_address(address, sect->align);
b0d623f7
A
327}
328
329/*******************************************************************************
330*******************************************************************************/
331kern_return_t
332kxld_sect_export_macho_to_file_buffer(const KXLDSect *sect, u_char *buf,
0a7de745 333 u_long *header_offset, u_long header_size, u_long *data_offset,
6d2010ae 334 u_long data_size, boolean_t is_32_bit __unused)
b0d623f7 335{
0a7de745
A
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;
b0d623f7
A
365
366finish:
0a7de745 367 return rval;
b0d623f7
A
368}
369
370/*******************************************************************************
0a7de745 371*******************************************************************************/
b0d623f7 372kern_return_t
39037602 373kxld_sect_export_macho_to_vm(const KXLDSect *sect,
0a7de745
A
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)
b0d623f7 380{
0a7de745
A
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
b0d623f7 400finish:
0a7de745 401 return rval;
b0d623f7
A
402}
403
404/*******************************************************************************
405*******************************************************************************/
406static kern_return_t
6d2010ae 407export_macho(const KXLDSect *sect, u_char *buf, u_long offset, u_long bufsize)
b0d623f7 408{
0a7de745
A
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:
39037602 452#if SPLIT_KEXTS_DEBUG
0a7de745
A
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__);
39037602 474#endif
0a7de745
A
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;
b0d623f7
A
490
491finish:
0a7de745 492 return rval;
b0d623f7
A
493}
494
495#if KXLD_USER_OR_ILP32
496/*******************************************************************************
497*******************************************************************************/
498static kern_return_t
0a7de745 499sect_export_macho_header_32(const KXLDSect *sect, u_char *buf,
b0d623f7
A
500 u_long *header_offset, u_long header_size, u_long data_offset)
501{
0a7de745
A
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;
b0d623f7 527
39037602 528#if SPLIT_KEXTS_DEBUG
0a7de745
A
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 }
39037602
A
541#endif
542
0a7de745 543 rval = KERN_SUCCESS;
b0d623f7
A
544
545finish:
0a7de745 546 return rval;
b0d623f7
A
547}
548#endif /* KXLD_USER_OR_ILP32 */
549
550#if KXLD_USER_OR_LP64
551/*******************************************************************************
552*******************************************************************************/
553static kern_return_t
0a7de745 554sect_export_macho_header_64(const KXLDSect *sect, u_char *buf,
b0d623f7
A
555 u_long *header_offset, u_long header_size, u_long data_offset)
556{
0a7de745
A
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;
b0d623f7 583
39037602 584#if SPLIT_KEXTS_DEBUG
0a7de745
A
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__);
39037602 603#endif
0a7de745
A
604
605 rval = KERN_SUCCESS;
b0d623f7
A
606
607finish:
0a7de745 608 return rval;
b0d623f7
A
609}
610#endif /* KXLD_USER_OR_LP64 */
611
612#if KXLD_USER_OR_COMMON
613/*******************************************************************************
614*******************************************************************************/
615kxld_size_t
616kxld_sect_grow(KXLDSect *sect, kxld_size_t nbytes, u_int align)
617{
0a7de745 618 kxld_size_t size = kxld_align_address(sect->size, align);
b0d623f7 619
0a7de745
A
620 if (align > sect->align) {
621 sect->align = align;
622 }
623 sect->size = size + nbytes;
b0d623f7 624
0a7de745 625 return size;
b0d623f7
A
626}
627#endif /* KXLD_USER_OR_COMMON */
628
629/*******************************************************************************
630*******************************************************************************/
631void
632kxld_sect_relocate(KXLDSect *sect, kxld_addr_t link_addr)
633{
39037602 634#if SPLIT_KEXTS_DEBUG
0a7de745
A
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 }
39037602
A
648#endif
649
0a7de745
A
650 sect->link_addr = kxld_sect_align_address(sect,
651 sect->link_addr + link_addr);
b0d623f7
A
652}
653
654#if KXLD_USER_OR_GOT
655/*******************************************************************************
656*******************************************************************************/
657kern_return_t
0a7de745 658kxld_sect_populate_got(KXLDSect *sect, KXLDSymtab *symtab,
b0d623f7
A
659 boolean_t swap __unused)
660{
0a7de745
A
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;
b0d623f7
A
681
682#if !KERNEL
0a7de745
A
683 if (swap) {
684 *entry = OSSwapInt64(*entry);
685 }
b0d623f7
A
686#endif /* !KERNEL */
687
0a7de745
A
688 ++entry;
689 entry_addr += sizeof(*entry);
690 }
b0d623f7 691
0a7de745 692 rval = KERN_SUCCESS;
b0d623f7
A
693
694finish:
0a7de745 695 return rval;
b0d623f7
A
696}
697#endif /* KXLD_USER_OR_GOT */
698
699/*******************************************************************************
700*******************************************************************************/
701kern_return_t
6d2010ae 702kxld_sect_process_relocs(KXLDSect *sect, KXLDRelocator *relocator)
b0d623f7 703{
0a7de745
A
704 kern_return_t rval = KERN_FAILURE;
705 KXLDReloc *reloc = NULL;
706 u_int i = 0;
b0d623f7 707
0a7de745
A
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 }
b0d623f7 713
0a7de745 714 rval = KERN_SUCCESS;
b0d623f7 715finish:
0a7de745 716 return rval;
b0d623f7 717}