2 * Copyright (c) 1998 Doug Rabson
3 * Copyright (c) 2004 Peter Wemm
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $FreeBSD: src/sys/kern/link_elf.c,v 1.24 1999/12/24 15:33:36 bde Exp $
30 #include <sys/param.h>
31 #include <sys/kernel.h>
32 #include <sys/systm.h>
33 #include <sys/malloc.h>
35 #include <sys/nlookup.h>
36 #include <sys/fcntl.h>
37 #include <sys/vnode.h>
38 #include <sys/linker.h>
39 #include <machine/elf.h>
42 #include <vm/vm_param.h>
43 #include <vm/vm_zone.h>
44 #include <vm/vm_object.h>
45 #include <vm/vm_kern.h>
46 #include <vm/vm_extern.h>
49 #include <vm/vm_map.h>
51 static int link_elf_obj_preload_file(const char *, linker_file_t
*);
52 static int link_elf_obj_preload_finish(linker_file_t
);
53 static int link_elf_obj_load_file(const char *, linker_file_t
*);
55 link_elf_obj_lookup_symbol(linker_file_t
, const char *,
57 static int link_elf_obj_symbol_values(linker_file_t
, c_linker_sym_t
, linker_symval_t
*);
59 link_elf_obj_search_symbol(linker_file_t
, caddr_t value
,
60 c_linker_sym_t
* sym
, long *diffp
);
62 static void link_elf_obj_unload_file(linker_file_t
);
64 link_elf_obj_lookup_set(linker_file_t
, const char *,
65 void ***, void ***, int *);
66 static void link_elf_obj_reloc_local(linker_file_t lf
);
67 static int elf_obj_lookup(linker_file_t lf
, Elf_Size symidx
, int deps
, Elf_Addr
*);
69 static struct linker_class_ops link_elf_obj_class_ops
= {
70 link_elf_obj_load_file
,
71 link_elf_obj_preload_file
,
74 static struct linker_file_ops link_elf_obj_file_ops
= {
75 .lookup_symbol
= link_elf_obj_lookup_symbol
,
76 .symbol_values
= link_elf_obj_symbol_values
,
77 .search_symbol
= link_elf_obj_search_symbol
,
78 .preload_finish
= link_elf_obj_preload_finish
,
79 .unload
= link_elf_obj_unload_file
,
80 .lookup_set
= link_elf_obj_lookup_set
,
87 int sec
; /* Original section */
104 typedef struct elf_file
{
107 caddr_t address
; /* Relocation address */
108 size_t bytes
; /* Chunk size in bytes */
109 vm_object_t object
; /* VM object to hold file pages */
112 Elf_progent
*progtab
;
115 Elf_relaent
*relatab
;
121 Elf_Sym
*ddbsymtab
; /* The symbol table we are using */
122 long ddbsymcnt
; /* Number of symbols */
123 caddr_t ddbstrtab
; /* String table */
124 long ddbstrcnt
; /* number of bytes in string table */
126 caddr_t shstrtab
; /* Section name string table */
127 long shstrcnt
; /* number of bytes in string table */
129 caddr_t ctftab
; /* CTF table */
130 long ctfcnt
; /* number of bytes in CTF table */
131 caddr_t ctfoff
; /* CTF offset table */
132 caddr_t typoff
; /* Type offset table */
133 long typlen
; /* Number of type entries. */
137 static int relocate_file(linker_file_t lf
);
140 * The kernel symbol table starts here.
142 extern struct _dynamic _DYNAMIC
;
145 link_elf_obj_init(void *arg
)
147 #if ELF_TARG_CLASS == ELFCLASS32
148 linker_add_class("elf32", NULL
, &link_elf_obj_class_ops
);
150 linker_add_class("elf64", NULL
, &link_elf_obj_class_ops
);
154 SYSINIT(link_elf
, SI_BOOT2_KLD
, SI_ORDER_SECOND
, link_elf_obj_init
, 0);
157 link_elf_obj_error(const char *file
, const char *s
)
159 kprintf("kldload: %s: %s\n", file
, s
);
163 link_elf_obj_preload_file(const char *filename
, linker_file_t
*result
)
168 caddr_t modptr
, baseptr
, sizeptr
;
173 int error
, i
, j
, pb
, ra
, rl
, shstrindex
, symstrindex
, symtabindex
;
176 * Look to see if we have the module preloaded.
178 modptr
= preload_search_by_name(filename
);
182 /* It's preloaded, check we can handle it and collect information */
183 type
= (char *)preload_search_info(modptr
, MODINFO_TYPE
);
184 baseptr
= preload_search_info(modptr
, MODINFO_ADDR
);
185 sizeptr
= preload_search_info(modptr
, MODINFO_SIZE
);
186 hdr
= (Elf_Ehdr
*) preload_search_info(modptr
, MODINFO_METADATA
|
188 shdr
= (Elf_Shdr
*) preload_search_info(modptr
, MODINFO_METADATA
|
191 (strcmp(type
, "elf" __XSTRING(__ELF_WORD_SIZE
) " obj module") != 0 &&
192 strcmp(type
, "elf obj module") != 0)) {
195 if (baseptr
== NULL
|| sizeptr
== NULL
|| hdr
== NULL
|| shdr
== NULL
)
198 ef
= kmalloc(sizeof(struct elf_file
), M_LINKER
, M_WAITOK
| M_ZERO
);
200 ef
->address
= *(caddr_t
*) baseptr
;
202 lf
= linker_make_file(filename
, ef
, &link_elf_obj_file_ops
);
207 lf
->address
= ef
->address
;
208 lf
->size
= *(size_t *) sizeptr
;
210 if (hdr
->e_ident
[EI_CLASS
] != ELF_TARG_CLASS
||
211 hdr
->e_ident
[EI_DATA
] != ELF_TARG_DATA
||
212 hdr
->e_ident
[EI_VERSION
] != EV_CURRENT
||
213 hdr
->e_version
!= EV_CURRENT
||
214 hdr
->e_type
!= ET_REL
||
215 hdr
->e_machine
!= ELF_TARG_MACH
) {
221 /* Scan the section header for information and table sizing. */
224 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
225 switch (shdr
[i
].sh_type
) {
232 symstrindex
= shdr
[i
].sh_link
;
243 shstrindex
= hdr
->e_shstrndx
;
244 if (ef
->nprogtab
== 0 || symstrindex
< 0 ||
245 symstrindex
>= hdr
->e_shnum
||
246 shdr
[symstrindex
].sh_type
!= SHT_STRTAB
|| shstrindex
== 0 ||
247 shstrindex
>= hdr
->e_shnum
||
248 shdr
[shstrindex
].sh_type
!= SHT_STRTAB
) {
252 /* Allocate space for tracking the load chunks */
253 if (ef
->nprogtab
!= 0)
254 ef
->progtab
= kmalloc(ef
->nprogtab
* sizeof(*ef
->progtab
),
255 M_LINKER
, M_WAITOK
| M_ZERO
);
256 if (ef
->nreltab
!= 0)
257 ef
->reltab
= kmalloc(ef
->nreltab
* sizeof(*ef
->reltab
),
258 M_LINKER
, M_WAITOK
| M_ZERO
);
259 if (ef
->nrelatab
!= 0)
260 ef
->relatab
= kmalloc(ef
->nrelatab
* sizeof(*ef
->relatab
),
261 M_LINKER
, M_WAITOK
| M_ZERO
);
262 if ((ef
->nprogtab
!= 0 && ef
->progtab
== NULL
) ||
263 (ef
->nreltab
!= 0 && ef
->reltab
== NULL
) ||
264 (ef
->nrelatab
!= 0 && ef
->relatab
== NULL
)) {
268 /* XXX, relocate the sh_addr fields saved by the loader. */
270 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
271 if (shdr
[i
].sh_addr
!= 0 && (off
== 0 || shdr
[i
].sh_addr
< off
))
272 off
= shdr
[i
].sh_addr
;
274 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
275 if (shdr
[i
].sh_addr
!= 0)
276 shdr
[i
].sh_addr
= shdr
[i
].sh_addr
- off
+
277 (Elf_Addr
) ef
->address
;
280 ef
->ddbsymcnt
= shdr
[symtabindex
].sh_size
/ sizeof(Elf_Sym
);
281 ef
->ddbsymtab
= (Elf_Sym
*) shdr
[symtabindex
].sh_addr
;
282 ef
->ddbstrcnt
= shdr
[symstrindex
].sh_size
;
283 ef
->ddbstrtab
= (char *)shdr
[symstrindex
].sh_addr
;
284 ef
->shstrcnt
= shdr
[shstrindex
].sh_size
;
285 ef
->shstrtab
= (char *)shdr
[shstrindex
].sh_addr
;
287 /* Now fill out progtab and the relocation tables. */
291 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
292 switch (shdr
[i
].sh_type
) {
295 ef
->progtab
[pb
].addr
= (void *)shdr
[i
].sh_addr
;
296 if (shdr
[i
].sh_type
== SHT_PROGBITS
)
297 ef
->progtab
[pb
].name
= "<<PROGBITS>>";
299 ef
->progtab
[pb
].name
= "<<NOBITS>>";
300 ef
->progtab
[pb
].size
= shdr
[i
].sh_size
;
301 ef
->progtab
[pb
].sec
= i
;
302 if (ef
->shstrtab
&& shdr
[i
].sh_name
!= 0)
303 ef
->progtab
[pb
].name
=
304 ef
->shstrtab
+ shdr
[i
].sh_name
;
306 if (ef
->progtab
[pb
].name
!= NULL
&&
307 !strcmp(ef
->progtab
[pb
].name
, "set_pcpu")) {
310 dpcpu
= dpcpu_alloc(shdr
[i
].sh_size
);
315 memcpy(dpcpu
, ef
->progtab
[pb
].addr
,
316 ef
->progtab
[pb
].size
);
317 dpcpu_copy(dpcpu
, shdr
[i
].sh_size
);
318 ef
->progtab
[pb
].addr
= dpcpu
;
320 } else if (ef
->progtab
[pb
].name
!= NULL
&&
321 !strcmp(ef
->progtab
[pb
].name
, VNET_SETNAME
)) {
324 vnet_data
= vnet_data_alloc(shdr
[i
].sh_size
);
325 if (vnet_data
== NULL
) {
329 memcpy(vnet_data
, ef
->progtab
[pb
].addr
,
330 ef
->progtab
[pb
].size
);
331 vnet_data_copy(vnet_data
, shdr
[i
].sh_size
);
332 ef
->progtab
[pb
].addr
= vnet_data
;
336 /* Update all symbol values with the offset. */
337 for (j
= 0; j
< ef
->ddbsymcnt
; j
++) {
338 es
= &ef
->ddbsymtab
[j
];
339 if (es
->st_shndx
!= i
)
341 es
->st_value
+= (Elf_Addr
) ef
->progtab
[pb
].addr
;
346 ef
->reltab
[rl
].rel
= (Elf_Rel
*) shdr
[i
].sh_addr
;
347 ef
->reltab
[rl
].nrel
= shdr
[i
].sh_size
/ sizeof(Elf_Rel
);
348 ef
->reltab
[rl
].sec
= shdr
[i
].sh_info
;
352 ef
->relatab
[ra
].rela
= (Elf_Rela
*) shdr
[i
].sh_addr
;
353 ef
->relatab
[ra
].nrela
=
354 shdr
[i
].sh_size
/ sizeof(Elf_Rela
);
355 ef
->relatab
[ra
].sec
= shdr
[i
].sh_info
;
360 if (pb
!= ef
->nprogtab
)
361 panic("lost progbits");
362 if (rl
!= ef
->nreltab
)
363 panic("lost reltab");
364 if (ra
!= ef
->nrelatab
)
365 panic("lost relatab");
367 /* Local intra-module relocations */
368 link_elf_obj_reloc_local(lf
);
374 /* preload not done this way */
375 linker_file_unload(lf
/* , LINKER_UNLOAD_FORCE */ );
380 link_elf_obj_preload_finish(linker_file_t lf
)
384 error
= relocate_file(lf
);
390 link_elf_obj_load_file(const char *filename
, linker_file_t
* result
)
392 struct nlookupdata nd
;
393 struct thread
*td
= curthread
; /* XXX */
394 struct proc
*p
= td
->td_proc
;
414 /* XXX Hack for firmware loading where p == NULL */
420 if (p
->p_ucred
== NULL
) {
421 kprintf("link_elf_obj_load_file: cannot load '%s' from filesystem"
422 " this early\n", filename
);
429 pathname
= linker_search_path(filename
);
430 if (pathname
== NULL
)
433 error
= nlookup_init(&nd
, pathname
, UIO_SYSSPACE
, NLC_FOLLOW
| NLC_LOCKVP
);
435 error
= vn_open(&nd
, NULL
, FREAD
, 0);
436 kfree(pathname
, M_LINKER
);
442 nd
.nl_open_vp
= NULL
;
446 * Read the elf header from the file.
448 hdr
= kmalloc(sizeof(*hdr
), M_LINKER
, M_WAITOK
);
449 error
= vn_rdwr(UIO_READ
, vp
, (void *)hdr
, sizeof(*hdr
), 0,
450 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
462 if (hdr
->e_ident
[EI_CLASS
] != ELF_TARG_CLASS
463 || hdr
->e_ident
[EI_DATA
] != ELF_TARG_DATA
) {
464 link_elf_obj_error(filename
, "Unsupported file layout");
468 if (hdr
->e_ident
[EI_VERSION
] != EV_CURRENT
469 || hdr
->e_version
!= EV_CURRENT
) {
470 link_elf_obj_error(filename
, "Unsupported file version");
474 if (hdr
->e_type
!= ET_REL
) {
478 if (hdr
->e_machine
!= ELF_TARG_MACH
) {
479 link_elf_obj_error(filename
, "Unsupported machine");
484 ef
= kmalloc(sizeof(struct elf_file
), M_LINKER
, M_WAITOK
| M_ZERO
);
485 lf
= linker_make_file(filename
, ef
, &link_elf_obj_file_ops
);
496 /* Allocate and read in the section header */
497 nbytes
= hdr
->e_shnum
* hdr
->e_shentsize
;
498 if (nbytes
== 0 || hdr
->e_shoff
== 0 ||
499 hdr
->e_shentsize
!= sizeof(Elf_Shdr
)) {
503 shdr
= kmalloc(nbytes
, M_LINKER
, M_WAITOK
);
505 error
= vn_rdwr(UIO_READ
, vp
, (caddr_t
) shdr
, nbytes
, hdr
->e_shoff
,
506 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
513 /* Scan the section header for information and table sizing. */
517 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
518 if (shdr
[i
].sh_size
== 0)
520 switch (shdr
[i
].sh_type
) {
528 symstrindex
= shdr
[i
].sh_link
;
540 if (ef
->nprogtab
== 0) {
541 link_elf_obj_error(filename
, "file has no contents");
546 /* Only allow one symbol table for now */
547 link_elf_obj_error(filename
, "file has no valid symbol table");
551 if (symstrindex
< 0 || symstrindex
> hdr
->e_shnum
||
552 shdr
[symstrindex
].sh_type
!= SHT_STRTAB
) {
553 link_elf_obj_error(filename
, "file has invalid symbol strings");
557 /* Allocate space for tracking the load chunks */
558 if (ef
->nprogtab
!= 0)
559 ef
->progtab
= kmalloc(ef
->nprogtab
* sizeof(*ef
->progtab
),
560 M_LINKER
, M_WAITOK
| M_ZERO
);
561 if (ef
->nreltab
!= 0)
562 ef
->reltab
= kmalloc(ef
->nreltab
* sizeof(*ef
->reltab
),
563 M_LINKER
, M_WAITOK
| M_ZERO
);
564 if (ef
->nrelatab
!= 0)
565 ef
->relatab
= kmalloc(ef
->nrelatab
* sizeof(*ef
->relatab
),
566 M_LINKER
, M_WAITOK
| M_ZERO
);
567 if ((ef
->nprogtab
!= 0 && ef
->progtab
== NULL
) ||
568 (ef
->nreltab
!= 0 && ef
->reltab
== NULL
) ||
569 (ef
->nrelatab
!= 0 && ef
->relatab
== NULL
)) {
573 if (symtabindex
== -1)
574 panic("lost symbol table index");
575 /* Allocate space for and load the symbol table */
576 ef
->ddbsymcnt
= shdr
[symtabindex
].sh_size
/ sizeof(Elf_Sym
);
577 ef
->ddbsymtab
= kmalloc(shdr
[symtabindex
].sh_size
, M_LINKER
, M_WAITOK
);
578 error
= vn_rdwr(UIO_READ
, vp
, (void *)ef
->ddbsymtab
,
579 shdr
[symtabindex
].sh_size
, shdr
[symtabindex
].sh_offset
,
580 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
587 if (symstrindex
== -1)
588 panic("lost symbol string index");
589 /* Allocate space for and load the symbol strings */
590 ef
->ddbstrcnt
= shdr
[symstrindex
].sh_size
;
591 ef
->ddbstrtab
= kmalloc(shdr
[symstrindex
].sh_size
, M_LINKER
, M_WAITOK
);
592 error
= vn_rdwr(UIO_READ
, vp
, ef
->ddbstrtab
,
593 shdr
[symstrindex
].sh_size
, shdr
[symstrindex
].sh_offset
,
594 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
601 /* Do we have a string table for the section names? */
603 if (hdr
->e_shstrndx
!= 0 &&
604 shdr
[hdr
->e_shstrndx
].sh_type
== SHT_STRTAB
) {
605 shstrindex
= hdr
->e_shstrndx
;
606 ef
->shstrcnt
= shdr
[shstrindex
].sh_size
;
607 ef
->shstrtab
= kmalloc(shdr
[shstrindex
].sh_size
, M_LINKER
,
609 error
= vn_rdwr(UIO_READ
, vp
, ef
->shstrtab
,
610 shdr
[shstrindex
].sh_size
, shdr
[shstrindex
].sh_offset
,
611 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
619 /* Size up code/data(progbits) and bss(nobits). */
621 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
622 if (shdr
[i
].sh_size
== 0)
624 switch (shdr
[i
].sh_type
) {
627 alignmask
= shdr
[i
].sh_addralign
- 1;
628 mapsize
+= alignmask
;
629 mapsize
&= ~alignmask
;
630 mapsize
+= shdr
[i
].sh_size
;
636 * We know how much space we need for the text/data/bss/etc. This
637 * stuff needs to be in a single chunk so that profiling etc can get
638 * the bounds and gdb can associate offsets with modules
640 ef
->object
= vm_object_allocate(OBJT_DEFAULT
,
641 round_page(mapsize
) >> PAGE_SHIFT
);
642 if (ef
->object
== NULL
) {
646 vm_object_hold(ef
->object
);
647 vm_object_reference_locked(ef
->object
);
648 ef
->address
= (caddr_t
) vm_map_min(kernel_map
);
652 * In order to satisfy x86_64's architectural requirements on the
653 * location of code and data in the kernel's address space, request a
654 * mapping that is above the kernel.
656 * vkernel64's text+data is outside the managed VM space entirely.
658 #if defined(__x86_64__) && defined(_KERNEL_VIRTUAL)
659 error
= vkernel_module_memory_alloc(&mapbase
, round_page(mapsize
));
660 vm_object_drop(ef
->object
);
663 error
= vm_map_find(kernel_map
, ef
->object
, NULL
,
664 0, &mapbase
, round_page(mapsize
),
666 VM_MAPTYPE_NORMAL
, VM_SUBSYS_IMGACT
,
667 VM_PROT_ALL
, VM_PROT_ALL
, FALSE
);
668 vm_object_drop(ef
->object
);
670 vm_object_deallocate(ef
->object
);
676 error
= vm_map_kernel_wiring(kernel_map
, mapbase
,
677 mapbase
+ round_page(mapsize
), 0);
679 if (error
!= KERN_SUCCESS
) {
683 /* Inform the kld system about the situation */
684 lf
->address
= ef
->address
= (caddr_t
) mapbase
;
685 lf
->size
= round_page(mapsize
);
689 * Now load code/data(progbits), zero bss(nobits), allocate space for
696 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
697 if (shdr
[i
].sh_size
== 0)
699 switch (shdr
[i
].sh_type
) {
702 alignmask
= shdr
[i
].sh_addralign
- 1;
703 mapbase
+= alignmask
;
704 mapbase
&= ~alignmask
;
705 if (ef
->shstrtab
&& shdr
[i
].sh_name
!= 0)
706 ef
->progtab
[pb
].name
=
707 ef
->shstrtab
+ shdr
[i
].sh_name
;
708 else if (shdr
[i
].sh_type
== SHT_PROGBITS
)
709 ef
->progtab
[pb
].name
= "<<PROGBITS>>";
711 ef
->progtab
[pb
].name
= "<<NOBITS>>";
713 if (ef
->progtab
[pb
].name
!= NULL
&&
714 !strcmp(ef
->progtab
[pb
].name
, "set_pcpu"))
715 ef
->progtab
[pb
].addr
=
716 dpcpu_alloc(shdr
[i
].sh_size
);
718 else if (ef
->progtab
[pb
].name
!= NULL
&&
719 !strcmp(ef
->progtab
[pb
].name
, VNET_SETNAME
))
720 ef
->progtab
[pb
].addr
=
721 vnet_data_alloc(shdr
[i
].sh_size
);
725 ef
->progtab
[pb
].addr
=
726 (void *)(uintptr_t) mapbase
;
727 if (ef
->progtab
[pb
].addr
== NULL
) {
731 ef
->progtab
[pb
].size
= shdr
[i
].sh_size
;
732 ef
->progtab
[pb
].sec
= i
;
733 if (shdr
[i
].sh_type
== SHT_PROGBITS
) {
734 error
= vn_rdwr(UIO_READ
, vp
,
735 ef
->progtab
[pb
].addr
,
736 shdr
[i
].sh_size
, shdr
[i
].sh_offset
,
737 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
,
746 /* Initialize the per-cpu or vnet area. */
747 if (ef
->progtab
[pb
].addr
!= (void *)mapbase
&&
748 !strcmp(ef
->progtab
[pb
].name
, "set_pcpu"))
749 dpcpu_copy(ef
->progtab
[pb
].addr
,
752 else if (ef
->progtab
[pb
].addr
!=
754 !strcmp(ef
->progtab
[pb
].name
, VNET_SETNAME
))
755 vnet_data_copy(ef
->progtab
[pb
].addr
,
760 bzero(ef
->progtab
[pb
].addr
, shdr
[i
].sh_size
);
762 /* Update all symbol values with the offset. */
763 for (j
= 0; j
< ef
->ddbsymcnt
; j
++) {
764 es
= &ef
->ddbsymtab
[j
];
765 if (es
->st_shndx
!= i
)
767 es
->st_value
+= (Elf_Addr
) ef
->progtab
[pb
].addr
;
769 mapbase
+= shdr
[i
].sh_size
;
773 ef
->reltab
[rl
].rel
= kmalloc(shdr
[i
].sh_size
, M_LINKER
, M_WAITOK
);
774 ef
->reltab
[rl
].nrel
= shdr
[i
].sh_size
/ sizeof(Elf_Rel
);
775 ef
->reltab
[rl
].sec
= shdr
[i
].sh_info
;
776 error
= vn_rdwr(UIO_READ
, vp
,
777 (void *)ef
->reltab
[rl
].rel
,
778 shdr
[i
].sh_size
, shdr
[i
].sh_offset
,
779 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
789 ef
->relatab
[ra
].rela
= kmalloc(shdr
[i
].sh_size
, M_LINKER
, M_WAITOK
);
790 ef
->relatab
[ra
].nrela
= shdr
[i
].sh_size
/ sizeof(Elf_Rela
);
791 ef
->relatab
[ra
].sec
= shdr
[i
].sh_info
;
792 error
= vn_rdwr(UIO_READ
, vp
,
793 (void *)ef
->relatab
[ra
].rela
,
794 shdr
[i
].sh_size
, shdr
[i
].sh_offset
,
795 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
806 if (pb
!= ef
->nprogtab
)
807 panic("lost progbits");
808 if (rl
!= ef
->nreltab
)
809 panic("lost reltab");
810 if (ra
!= ef
->nrelatab
)
811 panic("lost relatab");
812 if (mapbase
!= (vm_offset_t
) ef
->address
+ mapsize
)
813 panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)",
814 mapbase
, ef
->address
, mapsize
,
815 (vm_offset_t
) ef
->address
+ mapsize
);
817 /* Local intra-module relocations */
818 link_elf_obj_reloc_local(lf
);
820 /* Pull in dependencies */
821 error
= linker_load_dependencies(lf
);
825 /* External relocations */
826 error
= relocate_file(lf
);
834 linker_file_unload(lf
/*, LINKER_UNLOAD_FORCE */);
836 kfree(hdr
, M_LINKER
);
838 vn_close(vp
, FREAD
, NULL
);
844 link_elf_obj_unload_file(linker_file_t file
)
846 elf_file_t ef
= file
->priv
;
850 for (i
= 0; i
< ef
->nprogtab
; i
++) {
851 if (ef
->progtab
[i
].size
== 0)
853 if (ef
->progtab
[i
].name
== NULL
)
856 if (!strcmp(ef
->progtab
[i
].name
, "set_pcpu"))
857 dpcpu_free(ef
->progtab
[i
].addr
,
858 ef
->progtab
[i
].size
);
860 else if (!strcmp(ef
->progtab
[i
].name
, VNET_SETNAME
))
861 vnet_data_free(ef
->progtab
[i
].addr
,
862 ef
->progtab
[i
].size
);
869 kfree(ef
->reltab
, M_LINKER
);
871 kfree(ef
->relatab
, M_LINKER
);
873 kfree(ef
->progtab
, M_LINKER
);
875 kfree(ef
->ctftab
, M_LINKER
);
877 kfree(ef
->ctfoff
, M_LINKER
);
879 kfree(ef
->typoff
, M_LINKER
);
880 if (file
->pathname
!= NULL
)
881 preload_delete_name(file
->pathname
);
883 /* XXX reclaim module memory? */
887 for (i
= 0; i
< ef
->nreltab
; i
++)
888 if (ef
->reltab
[i
].rel
)
889 kfree(ef
->reltab
[i
].rel
, M_LINKER
);
890 for (i
= 0; i
< ef
->nrelatab
; i
++)
891 if (ef
->relatab
[i
].rela
)
892 kfree(ef
->relatab
[i
].rela
, M_LINKER
);
894 kfree(ef
->reltab
, M_LINKER
);
896 kfree(ef
->relatab
, M_LINKER
);
898 kfree(ef
->progtab
, M_LINKER
);
901 #if defined(__x86_64__) && defined(_KERNEL_VIRTUAL)
902 vkernel_module_memory_free((vm_offset_t
)ef
->address
, ef
->bytes
);
904 vm_map_remove(kernel_map
, (vm_offset_t
) ef
->address
,
905 (vm_offset_t
) ef
->address
+
906 (ef
->object
->size
<< PAGE_SHIFT
));
908 vm_object_deallocate(ef
->object
);
912 kfree(ef
->e_shdr
, M_LINKER
);
914 kfree(ef
->ddbsymtab
, M_LINKER
);
916 kfree(ef
->ddbstrtab
, M_LINKER
);
918 kfree(ef
->shstrtab
, M_LINKER
);
920 kfree(ef
->ctftab
, M_LINKER
);
922 kfree(ef
->ctfoff
, M_LINKER
);
924 kfree(ef
->typoff
, M_LINKER
);
929 symbol_name(elf_file_t ef
, Elf_Size r_info
)
933 if (ELF_R_SYM(r_info
)) {
934 ref
= ef
->ddbsymtab
+ ELF_R_SYM(r_info
);
935 return ef
->ddbstrtab
+ ref
->st_name
;
941 findbase(elf_file_t ef
, int sec
)
946 for (i
= 0; i
< ef
->nprogtab
; i
++) {
947 if (sec
== ef
->progtab
[i
].sec
) {
948 base
= (Elf_Addr
)ef
->progtab
[i
].addr
;
956 relocate_file(linker_file_t lf
)
958 elf_file_t ef
= lf
->priv
;
959 const Elf_Rel
*rellim
;
961 const Elf_Rela
*relalim
;
962 const Elf_Rela
*rela
;
969 /* Perform relocations without addend if there are any: */
970 for (i
= 0; i
< ef
->nreltab
; i
++) {
971 rel
= ef
->reltab
[i
].rel
;
973 panic("lost a reltab!");
974 rellim
= rel
+ ef
->reltab
[i
].nrel
;
975 base
= findbase(ef
, ef
->reltab
[i
].sec
);
977 panic("lost base for reltab");
978 for ( ; rel
< rellim
; rel
++) {
979 symidx
= ELF_R_SYM(rel
->r_info
);
980 if (symidx
>= ef
->ddbsymcnt
)
982 sym
= ef
->ddbsymtab
+ symidx
;
983 /* Local relocs are already done */
984 if (ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
)
986 if (elf_reloc(lf
, base
, rel
, ELF_RELOC_REL
,
988 symname
= symbol_name(ef
, rel
->r_info
);
989 kprintf("link_elf_obj_obj: symbol %s undefined\n",
996 /* Perform relocations with addend if there are any: */
997 for (i
= 0; i
< ef
->nrelatab
; i
++) {
998 rela
= ef
->relatab
[i
].rela
;
1000 panic("lost a relatab!");
1001 relalim
= rela
+ ef
->relatab
[i
].nrela
;
1002 base
= findbase(ef
, ef
->relatab
[i
].sec
);
1004 panic("lost base for relatab");
1005 for ( ; rela
< relalim
; rela
++) {
1006 symidx
= ELF_R_SYM(rela
->r_info
);
1007 if (symidx
>= ef
->ddbsymcnt
)
1009 sym
= ef
->ddbsymtab
+ symidx
;
1010 /* Local relocs are already done */
1011 if (ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
)
1013 if (elf_reloc(lf
, base
, rela
, ELF_RELOC_RELA
,
1015 symname
= symbol_name(ef
, rela
->r_info
);
1016 kprintf("link_elf_obj_obj: symbol %s undefined\n",
1027 link_elf_obj_lookup_symbol(linker_file_t lf
, const char *name
, c_linker_sym_t
*sym
)
1029 elf_file_t ef
= lf
->priv
;
1030 const Elf_Sym
*symp
;
1034 for (i
= 0, symp
= ef
->ddbsymtab
; i
< ef
->ddbsymcnt
; i
++, symp
++) {
1035 strp
= ef
->ddbstrtab
+ symp
->st_name
;
1036 if (symp
->st_shndx
!= SHN_UNDEF
&& strcmp(name
, strp
) == 0) {
1037 *sym
= (c_linker_sym_t
) symp
;
1045 link_elf_obj_symbol_values(linker_file_t lf
, c_linker_sym_t sym
,
1046 linker_symval_t
*symval
)
1048 elf_file_t ef
= lf
->priv
;
1049 const Elf_Sym
*es
= (const Elf_Sym
*) sym
;
1051 if (es
>= ef
->ddbsymtab
&& es
< (ef
->ddbsymtab
+ ef
->ddbsymcnt
)) {
1052 symval
->name
= ef
->ddbstrtab
+ es
->st_name
;
1053 symval
->value
= (caddr_t
)es
->st_value
;
1054 symval
->size
= es
->st_size
;
1061 link_elf_obj_search_symbol(linker_file_t lf
, caddr_t value
,
1062 c_linker_sym_t
*sym
, long *diffp
)
1064 elf_file_t ef
= lf
->priv
;
1065 u_long off
= (uintptr_t) (void *) value
;
1069 const Elf_Sym
*best
= NULL
;
1072 for (i
= 0, es
= ef
->ddbsymtab
; i
< ef
->ddbsymcnt
; i
++, es
++) {
1073 if (es
->st_name
== 0)
1075 st_value
= es
->st_value
;
1076 if (off
>= st_value
) {
1077 if (off
- st_value
< diff
) {
1078 diff
= off
- st_value
;
1082 } else if (off
- st_value
== diff
) {
1091 *sym
= (c_linker_sym_t
) best
;
1097 * Look up a linker set on an ELF system.
1100 link_elf_obj_lookup_set(linker_file_t lf
, const char *name
,
1101 void ***startp
, void ***stopp
, int *countp
)
1103 elf_file_t ef
= lf
->priv
;
1104 void **start
, **stop
;
1107 /* Relative to section number */
1108 for (i
= 0; i
< ef
->nprogtab
; i
++) {
1109 if ((strncmp(ef
->progtab
[i
].name
, "set_", 4) == 0) &&
1110 strcmp(ef
->progtab
[i
].name
+ 4, name
) == 0) {
1111 start
= (void **)ef
->progtab
[i
].addr
;
1112 stop
= (void **)((char *)ef
->progtab
[i
].addr
+
1113 ef
->progtab
[i
].size
);
1114 count
= stop
- start
;
1128 * Symbol lookup function that can be used when the symbol index is known (ie
1129 * in relocations). It uses the symbol index instead of doing a fully fledged
1130 * hash table based lookup when such is valid. For example for local symbols.
1131 * This is not only more efficient, it's also more correct. It's not always
1132 * the case that the symbol can be found through the hash table.
1135 elf_obj_lookup(linker_file_t lf
, Elf_Size symidx
, int deps
, Elf_Addr
*result
)
1137 elf_file_t ef
= lf
->priv
;
1141 /* Don't even try to lookup the symbol if the index is bogus. */
1142 if (symidx
>= ef
->ddbsymcnt
)
1145 sym
= ef
->ddbsymtab
+ symidx
;
1147 /* Quick answer if there is a definition included. */
1148 if (sym
->st_shndx
!= SHN_UNDEF
) {
1149 *result
= sym
->st_value
;
1153 /* If we get here, then it is undefined and needs a lookup. */
1154 switch (ELF_ST_BIND(sym
->st_info
)) {
1156 /* Local, but undefined? huh? */
1160 /* Relative to Data or Function name */
1161 symbol
= ef
->ddbstrtab
+ sym
->st_name
;
1163 /* Force a lookup failure if the symbol name is bogus. */
1166 return (linker_file_lookup_symbol(lf
, symbol
, deps
, (caddr_t
*)result
));
1169 kprintf("link_elf_obj_obj: Weak symbols not supported\n");
1178 link_elf_obj_fix_link_set(elf_file_t ef
)
1180 static const char startn
[] = "__start_";
1181 static const char stopn
[] = "__stop_";
1183 const char *sym_name
, *linkset_name
;
1184 Elf_Addr startp
, stopp
;
1189 for (symidx
= 1 /* zero entry is special */;
1190 symidx
< ef
->ddbsymcnt
; symidx
++) {
1191 sym
= ef
->ddbsymtab
+ symidx
;
1192 if (sym
->st_shndx
!= SHN_UNDEF
)
1195 sym_name
= ef
->ddbstrtab
+ sym
->st_name
;
1196 if (strncmp(sym_name
, startn
, sizeof(startn
) - 1) == 0) {
1198 linkset_name
= sym_name
+ sizeof(startn
) - 1;
1200 else if (strncmp(sym_name
, stopn
, sizeof(stopn
) - 1) == 0) {
1202 linkset_name
= sym_name
+ sizeof(stopn
) - 1;
1207 for (i
= 0; i
< ef
->nprogtab
; i
++) {
1208 if (strcmp(ef
->progtab
[i
].name
, linkset_name
) == 0) {
1209 startp
= (Elf_Addr
)ef
->progtab
[i
].addr
;
1210 stopp
= (Elf_Addr
)(startp
+ ef
->progtab
[i
].size
);
1214 if (i
== ef
->nprogtab
)
1217 sym
->st_value
= start
? startp
: stopp
;
1223 link_elf_obj_reloc_local(linker_file_t lf
)
1225 elf_file_t ef
= lf
->priv
;
1226 const Elf_Rel
*rellim
;
1228 const Elf_Rela
*relalim
;
1229 const Elf_Rela
*rela
;
1235 link_elf_obj_fix_link_set(ef
);
1237 /* Perform relocations without addend if there are any: */
1238 for (i
= 0; i
< ef
->nreltab
; i
++) {
1239 rel
= ef
->reltab
[i
].rel
;
1241 panic("lost a reltab!");
1242 rellim
= rel
+ ef
->reltab
[i
].nrel
;
1243 base
= findbase(ef
, ef
->reltab
[i
].sec
);
1245 panic("lost base for reltab");
1246 for ( ; rel
< rellim
; rel
++) {
1247 symidx
= ELF_R_SYM(rel
->r_info
);
1248 if (symidx
>= ef
->ddbsymcnt
)
1250 sym
= ef
->ddbsymtab
+ symidx
;
1251 /* Only do local relocs */
1252 if (ELF_ST_BIND(sym
->st_info
) != STB_LOCAL
)
1254 elf_reloc_local(lf
, base
, rel
, ELF_RELOC_REL
,
1259 /* Perform relocations with addend if there are any: */
1260 for (i
= 0; i
< ef
->nrelatab
; i
++) {
1261 rela
= ef
->relatab
[i
].rela
;
1263 panic("lost a relatab!");
1264 relalim
= rela
+ ef
->relatab
[i
].nrela
;
1265 base
= findbase(ef
, ef
->relatab
[i
].sec
);
1267 panic("lost base for relatab");
1268 for ( ; rela
< relalim
; rela
++) {
1269 symidx
= ELF_R_SYM(rela
->r_info
);
1270 if (symidx
>= ef
->ddbsymcnt
)
1272 sym
= ef
->ddbsymtab
+ symidx
;
1273 /* Only do local relocs */
1274 if (ELF_ST_BIND(sym
->st_info
) != STB_LOCAL
)
1276 elf_reloc_local(lf
, base
, rela
, ELF_RELOC_RELA
,