xref: /xnu-8796.101.5/libkern/kxld/kxld_sect.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
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
kxld_sect_init_from_macho_32(KXLDSect * sect,u_char * macho,u_long * sect_offset,u_int sectnum,const KXLDRelocator * relocator)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
kxld_sect_init_from_macho_64(KXLDSect * sect,u_char * macho,u_long * sect_offset,u_int sectnum,const KXLDRelocator * relocator)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
kxld_sect_init_got(KXLDSect * sect,u_int ngots)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
kxld_sect_init_zerofill(KXLDSect * sect,const char * segname,const char * sectname,kxld_size_t size,u_int align)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
kxld_sect_clear(KXLDSect * sect)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
kxld_sect_deinit(KXLDSect * sect)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
kxld_sect_get_num_relocs(const KXLDSect * sect)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
kxld_sect_get_macho_header_size(boolean_t is_32_bit)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
kxld_sect_get_macho_data_size(const KXLDSect * sect)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
kxld_sect_get_ngots(const KXLDSect * sect,const KXLDRelocator * relocator,const KXLDSymtab * symtab)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
kxld_sect_align_address(const KXLDSect * sect,kxld_addr_t address)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
kxld_sect_export_macho_to_file_buffer(const KXLDSect * sect,u_char * buf,u_long * header_offset,u_long header_size,u_long * data_offset,u_long data_size,boolean_t is_32_bit __unused)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
kxld_sect_export_macho_to_vm(const KXLDSect * sect,u_char * buf,u_long * header_offset,u_long header_size,kxld_addr_t link_addr,u_long data_size,boolean_t is_32_bit __unused)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
export_macho(const KXLDSect * sect,u_char * buf,u_long offset,u_long bufsize)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
sect_export_macho_header_32(const KXLDSect * sect,u_char * buf,u_long * header_offset,u_long header_size,u_long data_offset)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
sect_export_macho_header_64(const KXLDSect * sect,u_char * buf,u_long * header_offset,u_long header_size,u_long data_offset)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
kxld_sect_grow(KXLDSect * sect,kxld_size_t nbytes,u_int align)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
kxld_sect_relocate(KXLDSect * sect,kxld_addr_t link_addr)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
kxld_sect_populate_got(KXLDSect * sect,KXLDSymtab * symtab,boolean_t swap __unused)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
kxld_sect_process_relocs(KXLDSect * sect,KXLDRelocator * relocator)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 }
718