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
);
675 error
= vm_map_wire(&kernel_map
, mapbase
,
676 mapbase
+ round_page(mapsize
), 0);
678 if (error
!= KERN_SUCCESS
) {
682 /* Inform the kld system about the situation */
683 lf
->address
= ef
->address
= (caddr_t
) mapbase
;
684 lf
->size
= round_page(mapsize
);
688 * Now load code/data(progbits), zero bss(nobits), allocate space for
695 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
696 if (shdr
[i
].sh_size
== 0)
698 switch (shdr
[i
].sh_type
) {
701 alignmask
= shdr
[i
].sh_addralign
- 1;
702 mapbase
+= alignmask
;
703 mapbase
&= ~alignmask
;
704 if (ef
->shstrtab
&& shdr
[i
].sh_name
!= 0)
705 ef
->progtab
[pb
].name
=
706 ef
->shstrtab
+ shdr
[i
].sh_name
;
707 else if (shdr
[i
].sh_type
== SHT_PROGBITS
)
708 ef
->progtab
[pb
].name
= "<<PROGBITS>>";
710 ef
->progtab
[pb
].name
= "<<NOBITS>>";
712 if (ef
->progtab
[pb
].name
!= NULL
&&
713 !strcmp(ef
->progtab
[pb
].name
, "set_pcpu"))
714 ef
->progtab
[pb
].addr
=
715 dpcpu_alloc(shdr
[i
].sh_size
);
717 else if (ef
->progtab
[pb
].name
!= NULL
&&
718 !strcmp(ef
->progtab
[pb
].name
, VNET_SETNAME
))
719 ef
->progtab
[pb
].addr
=
720 vnet_data_alloc(shdr
[i
].sh_size
);
724 ef
->progtab
[pb
].addr
=
725 (void *)(uintptr_t) mapbase
;
726 if (ef
->progtab
[pb
].addr
== NULL
) {
730 ef
->progtab
[pb
].size
= shdr
[i
].sh_size
;
731 ef
->progtab
[pb
].sec
= i
;
732 if (shdr
[i
].sh_type
== SHT_PROGBITS
) {
733 error
= vn_rdwr(UIO_READ
, vp
,
734 ef
->progtab
[pb
].addr
,
735 shdr
[i
].sh_size
, shdr
[i
].sh_offset
,
736 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
,
745 /* Initialize the per-cpu or vnet area. */
746 if (ef
->progtab
[pb
].addr
!= (void *)mapbase
&&
747 !strcmp(ef
->progtab
[pb
].name
, "set_pcpu"))
748 dpcpu_copy(ef
->progtab
[pb
].addr
,
751 else if (ef
->progtab
[pb
].addr
!=
753 !strcmp(ef
->progtab
[pb
].name
, VNET_SETNAME
))
754 vnet_data_copy(ef
->progtab
[pb
].addr
,
759 bzero(ef
->progtab
[pb
].addr
, shdr
[i
].sh_size
);
761 /* Update all symbol values with the offset. */
762 for (j
= 0; j
< ef
->ddbsymcnt
; j
++) {
763 es
= &ef
->ddbsymtab
[j
];
764 if (es
->st_shndx
!= i
)
766 es
->st_value
+= (Elf_Addr
) ef
->progtab
[pb
].addr
;
768 mapbase
+= shdr
[i
].sh_size
;
772 ef
->reltab
[rl
].rel
= kmalloc(shdr
[i
].sh_size
, M_LINKER
, M_WAITOK
);
773 ef
->reltab
[rl
].nrel
= shdr
[i
].sh_size
/ sizeof(Elf_Rel
);
774 ef
->reltab
[rl
].sec
= shdr
[i
].sh_info
;
775 error
= vn_rdwr(UIO_READ
, vp
,
776 (void *)ef
->reltab
[rl
].rel
,
777 shdr
[i
].sh_size
, shdr
[i
].sh_offset
,
778 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
788 ef
->relatab
[ra
].rela
= kmalloc(shdr
[i
].sh_size
, M_LINKER
, M_WAITOK
);
789 ef
->relatab
[ra
].nrela
= shdr
[i
].sh_size
/ sizeof(Elf_Rela
);
790 ef
->relatab
[ra
].sec
= shdr
[i
].sh_info
;
791 error
= vn_rdwr(UIO_READ
, vp
,
792 (void *)ef
->relatab
[ra
].rela
,
793 shdr
[i
].sh_size
, shdr
[i
].sh_offset
,
794 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
805 if (pb
!= ef
->nprogtab
)
806 panic("lost progbits");
807 if (rl
!= ef
->nreltab
)
808 panic("lost reltab");
809 if (ra
!= ef
->nrelatab
)
810 panic("lost relatab");
811 if (mapbase
!= (vm_offset_t
) ef
->address
+ mapsize
)
812 panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)",
813 mapbase
, ef
->address
, mapsize
,
814 (vm_offset_t
) ef
->address
+ mapsize
);
816 /* Local intra-module relocations */
817 link_elf_obj_reloc_local(lf
);
819 /* Pull in dependencies */
820 error
= linker_load_dependencies(lf
);
824 /* External relocations */
825 error
= relocate_file(lf
);
833 linker_file_unload(lf
/*, LINKER_UNLOAD_FORCE */);
835 kfree(hdr
, M_LINKER
);
837 vn_close(vp
, FREAD
, NULL
);
843 link_elf_obj_unload_file(linker_file_t file
)
845 elf_file_t ef
= file
->priv
;
849 for (i
= 0; i
< ef
->nprogtab
; i
++) {
850 if (ef
->progtab
[i
].size
== 0)
852 if (ef
->progtab
[i
].name
== NULL
)
855 if (!strcmp(ef
->progtab
[i
].name
, "set_pcpu"))
856 dpcpu_free(ef
->progtab
[i
].addr
,
857 ef
->progtab
[i
].size
);
859 else if (!strcmp(ef
->progtab
[i
].name
, VNET_SETNAME
))
860 vnet_data_free(ef
->progtab
[i
].addr
,
861 ef
->progtab
[i
].size
);
868 kfree(ef
->reltab
, M_LINKER
);
870 kfree(ef
->relatab
, M_LINKER
);
872 kfree(ef
->progtab
, M_LINKER
);
874 kfree(ef
->ctftab
, M_LINKER
);
876 kfree(ef
->ctfoff
, M_LINKER
);
878 kfree(ef
->typoff
, M_LINKER
);
879 if (file
->filename
!= NULL
)
880 preload_delete_name(file
->filename
);
882 /* XXX reclaim module memory? */
886 for (i
= 0; i
< ef
->nreltab
; i
++)
887 if (ef
->reltab
[i
].rel
)
888 kfree(ef
->reltab
[i
].rel
, M_LINKER
);
889 for (i
= 0; i
< ef
->nrelatab
; i
++)
890 if (ef
->relatab
[i
].rela
)
891 kfree(ef
->relatab
[i
].rela
, M_LINKER
);
893 kfree(ef
->reltab
, M_LINKER
);
895 kfree(ef
->relatab
, M_LINKER
);
897 kfree(ef
->progtab
, M_LINKER
);
900 #if defined(__x86_64__) && defined(_KERNEL_VIRTUAL)
901 vkernel_module_memory_free((vm_offset_t
)ef
->address
, ef
->bytes
);
903 vm_map_remove(&kernel_map
, (vm_offset_t
) ef
->address
,
904 (vm_offset_t
) ef
->address
+
905 (ef
->object
->size
<< PAGE_SHIFT
));
907 vm_object_deallocate(ef
->object
);
911 kfree(ef
->e_shdr
, M_LINKER
);
913 kfree(ef
->ddbsymtab
, M_LINKER
);
915 kfree(ef
->ddbstrtab
, M_LINKER
);
917 kfree(ef
->shstrtab
, M_LINKER
);
919 kfree(ef
->ctftab
, M_LINKER
);
921 kfree(ef
->ctfoff
, M_LINKER
);
923 kfree(ef
->typoff
, M_LINKER
);
928 symbol_name(elf_file_t ef
, Elf_Size r_info
)
932 if (ELF_R_SYM(r_info
)) {
933 ref
= ef
->ddbsymtab
+ ELF_R_SYM(r_info
);
934 return ef
->ddbstrtab
+ ref
->st_name
;
940 findbase(elf_file_t ef
, int sec
)
945 for (i
= 0; i
< ef
->nprogtab
; i
++) {
946 if (sec
== ef
->progtab
[i
].sec
) {
947 base
= (Elf_Addr
)ef
->progtab
[i
].addr
;
955 relocate_file(linker_file_t lf
)
957 elf_file_t ef
= lf
->priv
;
958 const Elf_Rel
*rellim
;
960 const Elf_Rela
*relalim
;
961 const Elf_Rela
*rela
;
968 /* Perform relocations without addend if there are any: */
969 for (i
= 0; i
< ef
->nreltab
; i
++) {
970 rel
= ef
->reltab
[i
].rel
;
972 panic("lost a reltab!");
973 rellim
= rel
+ ef
->reltab
[i
].nrel
;
974 base
= findbase(ef
, ef
->reltab
[i
].sec
);
976 panic("lost base for reltab");
977 for ( ; rel
< rellim
; rel
++) {
978 symidx
= ELF_R_SYM(rel
->r_info
);
979 if (symidx
>= ef
->ddbsymcnt
)
981 sym
= ef
->ddbsymtab
+ symidx
;
982 /* Local relocs are already done */
983 if (ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
)
985 if (elf_reloc(lf
, base
, rel
, ELF_RELOC_REL
,
987 symname
= symbol_name(ef
, rel
->r_info
);
988 kprintf("link_elf_obj_obj: symbol %s undefined\n",
995 /* Perform relocations with addend if there are any: */
996 for (i
= 0; i
< ef
->nrelatab
; i
++) {
997 rela
= ef
->relatab
[i
].rela
;
999 panic("lost a relatab!");
1000 relalim
= rela
+ ef
->relatab
[i
].nrela
;
1001 base
= findbase(ef
, ef
->relatab
[i
].sec
);
1003 panic("lost base for relatab");
1004 for ( ; rela
< relalim
; rela
++) {
1005 symidx
= ELF_R_SYM(rela
->r_info
);
1006 if (symidx
>= ef
->ddbsymcnt
)
1008 sym
= ef
->ddbsymtab
+ symidx
;
1009 /* Local relocs are already done */
1010 if (ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
)
1012 if (elf_reloc(lf
, base
, rela
, ELF_RELOC_RELA
,
1014 symname
= symbol_name(ef
, rela
->r_info
);
1015 kprintf("link_elf_obj_obj: symbol %s undefined\n",
1026 link_elf_obj_lookup_symbol(linker_file_t lf
, const char *name
, c_linker_sym_t
*sym
)
1028 elf_file_t ef
= lf
->priv
;
1029 const Elf_Sym
*symp
;
1033 for (i
= 0, symp
= ef
->ddbsymtab
; i
< ef
->ddbsymcnt
; i
++, symp
++) {
1034 strp
= ef
->ddbstrtab
+ symp
->st_name
;
1035 if (symp
->st_shndx
!= SHN_UNDEF
&& strcmp(name
, strp
) == 0) {
1036 *sym
= (c_linker_sym_t
) symp
;
1044 link_elf_obj_symbol_values(linker_file_t lf
, c_linker_sym_t sym
,
1045 linker_symval_t
*symval
)
1047 elf_file_t ef
= lf
->priv
;
1048 const Elf_Sym
*es
= (const Elf_Sym
*) sym
;
1050 if (es
>= ef
->ddbsymtab
&& es
< (ef
->ddbsymtab
+ ef
->ddbsymcnt
)) {
1051 symval
->name
= ef
->ddbstrtab
+ es
->st_name
;
1052 symval
->value
= (caddr_t
)es
->st_value
;
1053 symval
->size
= es
->st_size
;
1060 link_elf_obj_search_symbol(linker_file_t lf
, caddr_t value
,
1061 c_linker_sym_t
*sym
, long *diffp
)
1063 elf_file_t ef
= lf
->priv
;
1064 u_long off
= (uintptr_t) (void *) value
;
1068 const Elf_Sym
*best
= NULL
;
1071 for (i
= 0, es
= ef
->ddbsymtab
; i
< ef
->ddbsymcnt
; i
++, es
++) {
1072 if (es
->st_name
== 0)
1074 st_value
= es
->st_value
;
1075 if (off
>= st_value
) {
1076 if (off
- st_value
< diff
) {
1077 diff
= off
- st_value
;
1081 } else if (off
- st_value
== diff
) {
1090 *sym
= (c_linker_sym_t
) best
;
1096 * Look up a linker set on an ELF system.
1099 link_elf_obj_lookup_set(linker_file_t lf
, const char *name
,
1100 void ***startp
, void ***stopp
, int *countp
)
1102 elf_file_t ef
= lf
->priv
;
1103 void **start
, **stop
;
1106 /* Relative to section number */
1107 for (i
= 0; i
< ef
->nprogtab
; i
++) {
1108 if ((strncmp(ef
->progtab
[i
].name
, "set_", 4) == 0) &&
1109 strcmp(ef
->progtab
[i
].name
+ 4, name
) == 0) {
1110 start
= (void **)ef
->progtab
[i
].addr
;
1111 stop
= (void **)((char *)ef
->progtab
[i
].addr
+
1112 ef
->progtab
[i
].size
);
1113 count
= stop
- start
;
1127 * Symbol lookup function that can be used when the symbol index is known (ie
1128 * in relocations). It uses the symbol index instead of doing a fully fledged
1129 * hash table based lookup when such is valid. For example for local symbols.
1130 * This is not only more efficient, it's also more correct. It's not always
1131 * the case that the symbol can be found through the hash table.
1134 elf_obj_lookup(linker_file_t lf
, Elf_Size symidx
, int deps
, Elf_Addr
*result
)
1136 elf_file_t ef
= lf
->priv
;
1140 /* Don't even try to lookup the symbol if the index is bogus. */
1141 if (symidx
>= ef
->ddbsymcnt
)
1144 sym
= ef
->ddbsymtab
+ symidx
;
1146 /* Quick answer if there is a definition included. */
1147 if (sym
->st_shndx
!= SHN_UNDEF
) {
1148 *result
= sym
->st_value
;
1152 /* If we get here, then it is undefined and needs a lookup. */
1153 switch (ELF_ST_BIND(sym
->st_info
)) {
1155 /* Local, but undefined? huh? */
1159 /* Relative to Data or Function name */
1160 symbol
= ef
->ddbstrtab
+ sym
->st_name
;
1162 /* Force a lookup failure if the symbol name is bogus. */
1165 return (linker_file_lookup_symbol(lf
, symbol
, deps
, (caddr_t
*)result
));
1168 kprintf("link_elf_obj_obj: Weak symbols not supported\n");
1177 link_elf_obj_fix_link_set(elf_file_t ef
)
1179 static const char startn
[] = "__start_";
1180 static const char stopn
[] = "__stop_";
1182 const char *sym_name
, *linkset_name
;
1183 Elf_Addr startp
, stopp
;
1188 for (symidx
= 1 /* zero entry is special */;
1189 symidx
< ef
->ddbsymcnt
; symidx
++) {
1190 sym
= ef
->ddbsymtab
+ symidx
;
1191 if (sym
->st_shndx
!= SHN_UNDEF
)
1194 sym_name
= ef
->ddbstrtab
+ sym
->st_name
;
1195 if (strncmp(sym_name
, startn
, sizeof(startn
) - 1) == 0) {
1197 linkset_name
= sym_name
+ sizeof(startn
) - 1;
1199 else if (strncmp(sym_name
, stopn
, sizeof(stopn
) - 1) == 0) {
1201 linkset_name
= sym_name
+ sizeof(stopn
) - 1;
1206 for (i
= 0; i
< ef
->nprogtab
; i
++) {
1207 if (strcmp(ef
->progtab
[i
].name
, linkset_name
) == 0) {
1208 startp
= (Elf_Addr
)ef
->progtab
[i
].addr
;
1209 stopp
= (Elf_Addr
)(startp
+ ef
->progtab
[i
].size
);
1213 if (i
== ef
->nprogtab
)
1216 sym
->st_value
= start
? startp
: stopp
;
1222 link_elf_obj_reloc_local(linker_file_t lf
)
1224 elf_file_t ef
= lf
->priv
;
1225 const Elf_Rel
*rellim
;
1227 const Elf_Rela
*relalim
;
1228 const Elf_Rela
*rela
;
1234 link_elf_obj_fix_link_set(ef
);
1236 /* Perform relocations without addend if there are any: */
1237 for (i
= 0; i
< ef
->nreltab
; i
++) {
1238 rel
= ef
->reltab
[i
].rel
;
1240 panic("lost a reltab!");
1241 rellim
= rel
+ ef
->reltab
[i
].nrel
;
1242 base
= findbase(ef
, ef
->reltab
[i
].sec
);
1244 panic("lost base for reltab");
1245 for ( ; rel
< rellim
; rel
++) {
1246 symidx
= ELF_R_SYM(rel
->r_info
);
1247 if (symidx
>= ef
->ddbsymcnt
)
1249 sym
= ef
->ddbsymtab
+ symidx
;
1250 /* Only do local relocs */
1251 if (ELF_ST_BIND(sym
->st_info
) != STB_LOCAL
)
1253 elf_reloc_local(lf
, base
, rel
, ELF_RELOC_REL
,
1258 /* Perform relocations with addend if there are any: */
1259 for (i
= 0; i
< ef
->nrelatab
; i
++) {
1260 rela
= ef
->relatab
[i
].rela
;
1262 panic("lost a relatab!");
1263 relalim
= rela
+ ef
->relatab
[i
].nrela
;
1264 base
= findbase(ef
, ef
->relatab
[i
].sec
);
1266 panic("lost base for relatab");
1267 for ( ; rela
< relalim
; rela
++) {
1268 symidx
= ELF_R_SYM(rela
->r_info
);
1269 if (symidx
>= ef
->ddbsymcnt
)
1271 sym
= ef
->ddbsymtab
+ symidx
;
1272 /* Only do local relocs */
1273 if (ELF_ST_BIND(sym
->st_info
) != STB_LOCAL
)
1275 elf_reloc_local(lf
, base
, rela
, ELF_RELOC_RELA
,