2 * Copyright (c) 1998 Doug Rabson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/sys/kern/link_elf.c,v 1.24 1999/12/24 15:33:36 bde Exp $
27 * $DragonFly: src/sys/kern/link_elf.c,v 1.29 2008/08/01 23:11:16 dillon 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>
46 #include <vm/vm_object.h>
47 #include <vm/vm_kern.h>
48 #include <vm/vm_extern.h>
51 #include <vm/vm_map.h>
53 #if defined(__amd64__) && defined(_KERNEL_VIRTUAL)
57 static int link_elf_preload_file(const char *, linker_file_t
*);
58 static int link_elf_preload_finish(linker_file_t
);
59 static int link_elf_load_file(const char*, linker_file_t
*);
60 static int link_elf_lookup_symbol(linker_file_t
, const char*,
62 static int link_elf_symbol_values(linker_file_t
, c_linker_sym_t
, linker_symval_t
*);
63 static int link_elf_search_symbol(linker_file_t
, caddr_t value
,
64 c_linker_sym_t
* sym
, long* diffp
);
66 static void link_elf_unload_file(linker_file_t
);
67 static void link_elf_unload_module(linker_file_t
);
68 static int link_elf_lookup_set(linker_file_t
, const char *,
69 void ***, void ***, int *);
70 static int elf_lookup(linker_file_t lf
, Elf_Size symidx
, int deps
, Elf_Addr
*);
71 static void link_elf_reloc_local(linker_file_t lf
);
73 static struct linker_class_ops link_elf_class_ops
= {
75 link_elf_preload_file
,
78 static struct linker_file_ops link_elf_file_ops
= {
79 .lookup_symbol
= link_elf_lookup_symbol
,
80 .symbol_values
= link_elf_symbol_values
,
81 .search_symbol
= link_elf_search_symbol
,
82 .unload
= link_elf_unload_file
,
83 .lookup_set
= link_elf_lookup_set
86 static struct linker_file_ops link_elf_module_ops
= {
87 .lookup_symbol
= link_elf_lookup_symbol
,
88 .symbol_values
= link_elf_symbol_values
,
89 .search_symbol
= link_elf_search_symbol
,
90 .preload_finish
= link_elf_preload_finish
,
91 .unload
= link_elf_unload_module
,
92 .lookup_set
= link_elf_lookup_set
,
95 typedef struct elf_file
{
96 caddr_t address
; /* Relocation address */
98 vm_object_t object
; /* VM object to hold file pages */
100 const Elf_Dyn
* dynamic
; /* Symbol table etc. */
101 Elf_Hashelt nbuckets
; /* DT_HASH info */
103 const Elf_Hashelt
* buckets
;
104 const Elf_Hashelt
* chains
;
106 caddr_t strtab
; /* DT_STRTAB */
107 int strsz
; /* DT_STRSZ */
108 const Elf_Sym
* symtab
; /* DT_SYMTAB */
109 Elf_Addr
* got
; /* DT_PLTGOT */
110 const Elf_Rel
* pltrel
; /* DT_JMPREL */
111 int pltrelsize
; /* DT_PLTRELSZ */
112 const Elf_Rela
* pltrela
; /* DT_JMPREL */
113 int pltrelasize
; /* DT_PLTRELSZ */
114 const Elf_Rel
* rel
; /* DT_REL */
115 int relsize
; /* DT_RELSZ */
116 const Elf_Rela
* rela
; /* DT_RELA */
117 int relasize
; /* DT_RELASZ */
119 const Elf_Sym
* ddbsymtab
; /* The symbol table we are using */
120 long ddbsymcnt
; /* Number of symbols */
121 caddr_t ddbstrtab
; /* String table */
122 long ddbstrcnt
; /* number of bytes in string table */
123 caddr_t symbase
; /* malloc'ed symbold base */
124 caddr_t strbase
; /* malloc'ed string base */
127 static int parse_dynamic(linker_file_t lf
);
128 static int relocate_file(linker_file_t lf
);
129 static int parse_module_symbols(linker_file_t lf
);
132 * The kernel symbol table starts here.
134 extern struct _dynamic _DYNAMIC
;
137 link_elf_init(void* arg
)
140 caddr_t modptr
, baseptr
, sizeptr
;
144 #if ELF_TARG_CLASS == ELFCLASS32
145 linker_add_class("elf32", NULL
, &link_elf_class_ops
);
147 linker_add_class("elf64", NULL
, &link_elf_class_ops
);
150 dp
= (Elf_Dyn
*) &_DYNAMIC
;
152 ef
= kmalloc(sizeof(struct elf_file
), M_LINKER
, M_INTWAIT
| M_ZERO
);
154 #ifdef SPARSE_MAPPING
159 modptr
= preload_search_by_type("elf kernel");
161 modname
= (char *)preload_search_info(modptr
, MODINFO_NAME
);
164 linker_kernel_file
= linker_make_file(modname
, ef
, &link_elf_file_ops
);
165 if (linker_kernel_file
== NULL
)
166 panic("link_elf_init: Can't create linker structures for kernel");
167 parse_dynamic(linker_kernel_file
);
168 #if defined(__amd64__) && defined(_KERNEL_VIRTUAL)
169 fprintf(stderr
, "WARNING: KERNBASE being used\n");
171 linker_kernel_file
->address
= (caddr_t
) KERNBASE
;
172 linker_kernel_file
->size
= -(intptr_t)linker_kernel_file
->address
;
176 baseptr
= preload_search_info(modptr
, MODINFO_ADDR
);
178 linker_kernel_file
->address
= *(caddr_t
*)baseptr
;
179 sizeptr
= preload_search_info(modptr
, MODINFO_SIZE
);
181 linker_kernel_file
->size
= *(size_t *)sizeptr
;
183 parse_module_symbols(linker_kernel_file
);
184 linker_current_file
= linker_kernel_file
;
185 linker_kernel_file
->flags
|= LINKER_FILE_LINKED
;
189 SYSINIT(link_elf
, SI_BOOT2_KLD
, SI_ORDER_SECOND
, link_elf_init
, 0);
192 parse_module_symbols(linker_file_t lf
)
194 elf_file_t ef
= lf
->priv
;
196 caddr_t ssym
, esym
, base
;
202 if (ef
->modptr
== NULL
)
204 pointer
= preload_search_info(ef
->modptr
, MODINFO_METADATA
|MODINFOMD_SSYM
);
207 ssym
= *(caddr_t
*)pointer
;
208 pointer
= preload_search_info(ef
->modptr
, MODINFO_METADATA
|MODINFOMD_ESYM
);
211 esym
= *(caddr_t
*)pointer
;
215 symcnt
= *(long *)base
;
216 base
+= sizeof(long);
217 symtab
= (Elf_Sym
*)base
;
218 base
+= roundup(symcnt
, sizeof(long));
220 if (base
> esym
|| base
< ssym
) {
221 kprintf("Symbols are corrupt!\n");
225 strcnt
= *(long *)base
;
226 base
+= sizeof(long);
228 base
+= roundup(strcnt
, sizeof(long));
230 if (base
> esym
|| base
< ssym
) {
231 kprintf("Symbols are corrupt!\n");
235 ef
->ddbsymtab
= symtab
;
236 ef
->ddbsymcnt
= symcnt
/ sizeof(Elf_Sym
);
237 ef
->ddbstrtab
= strtab
;
238 ef
->ddbstrcnt
= strcnt
;
244 parse_dynamic(linker_file_t lf
)
246 elf_file_t ef
= lf
->priv
;
248 int plttype
= DT_REL
;
250 for (dp
= ef
->dynamic
; dp
->d_tag
!= DT_NULL
; dp
++) {
254 /* From src/libexec/rtld-elf/rtld.c */
255 const Elf_Hashelt
*hashtab
= (const Elf_Hashelt
*)
256 (ef
->address
+ dp
->d_un
.d_ptr
);
257 ef
->nbuckets
= hashtab
[0];
258 ef
->nchains
= hashtab
[1];
259 ef
->buckets
= hashtab
+ 2;
260 ef
->chains
= ef
->buckets
+ ef
->nbuckets
;
264 ef
->strtab
= (caddr_t
) (ef
->address
+ dp
->d_un
.d_ptr
);
267 ef
->strsz
= dp
->d_un
.d_val
;
270 ef
->symtab
= (Elf_Sym
*) (ef
->address
+ dp
->d_un
.d_ptr
);
273 if (dp
->d_un
.d_val
!= sizeof(Elf_Sym
))
277 ef
->got
= (Elf_Addr
*) (ef
->address
+ dp
->d_un
.d_ptr
);
280 ef
->rel
= (const Elf_Rel
*) (ef
->address
+ dp
->d_un
.d_ptr
);
283 ef
->relsize
= dp
->d_un
.d_val
;
286 if (dp
->d_un
.d_val
!= sizeof(Elf_Rel
))
290 ef
->pltrel
= (const Elf_Rel
*) (ef
->address
+ dp
->d_un
.d_ptr
);
293 ef
->pltrelsize
= dp
->d_un
.d_val
;
296 ef
->rela
= (const Elf_Rela
*) (ef
->address
+ dp
->d_un
.d_ptr
);
299 ef
->relasize
= dp
->d_un
.d_val
;
302 if (dp
->d_un
.d_val
!= sizeof(Elf_Rela
))
306 plttype
= dp
->d_un
.d_val
;
307 if (plttype
!= DT_REL
&& plttype
!= DT_RELA
)
313 if (plttype
== DT_RELA
) {
314 ef
->pltrela
= (const Elf_Rela
*) ef
->pltrel
;
316 ef
->pltrelasize
= ef
->pltrelsize
;
320 ef
->ddbsymtab
= ef
->symtab
;
321 ef
->ddbsymcnt
= ef
->nchains
;
322 ef
->ddbstrtab
= ef
->strtab
;
323 ef
->ddbstrcnt
= ef
->strsz
;
329 link_elf_error(const char *s
)
331 kprintf("kldload: %s\n", s
);
335 link_elf_preload_file(const char *filename
, linker_file_t
*result
)
337 caddr_t modptr
, baseptr
, sizeptr
, dynptr
;
345 * Look to see if we have the module preloaded.
347 modptr
= preload_search_by_name(filename
);
351 /* It's preloaded, check we can handle it and collect information */
352 type
= (char *)preload_search_info(modptr
, MODINFO_TYPE
);
353 baseptr
= preload_search_info(modptr
, MODINFO_ADDR
);
354 sizeptr
= preload_search_info(modptr
, MODINFO_SIZE
);
355 dynptr
= preload_search_info(modptr
, MODINFO_METADATA
|MODINFOMD_DYNAMIC
);
357 (strcmp(type
, "elf" __XSTRING(__ELF_WORD_SIZE
) " module") != 0 &&
358 strcmp(type
, "elf module") != 0))
360 if (baseptr
== NULL
|| sizeptr
== NULL
|| dynptr
== NULL
)
363 ef
= kmalloc(sizeof(struct elf_file
), M_LINKER
, M_WAITOK
| M_ZERO
);
365 ef
->address
= *(caddr_t
*)baseptr
;
366 #ifdef SPARSE_MAPPING
369 dp
= (vm_offset_t
)ef
->address
+ *(vm_offset_t
*)dynptr
;
370 ef
->dynamic
= (Elf_Dyn
*)dp
;
371 lf
= linker_make_file(filename
, ef
, &link_elf_module_ops
);
376 lf
->address
= ef
->address
;
377 lf
->size
= *(size_t *)sizeptr
;
379 error
= parse_dynamic(lf
);
381 linker_file_unload(lf
);
384 link_elf_reloc_local(lf
);
390 link_elf_preload_finish(linker_file_t lf
)
394 error
= relocate_file(lf
);
397 parse_module_symbols(lf
);
403 link_elf_load_file(const char* filename
, linker_file_t
* result
)
405 struct nlookupdata nd
;
406 struct thread
*td
= curthread
; /* XXX */
407 struct proc
*p
= td
->td_proc
;
422 Elf_Addr base_vlimit
;
434 /* XXX Hack for firmware loading where p == NULL */
440 if (p
->p_ucred
== NULL
) {
441 kprintf("link_elf_load_file: cannot load '%s' from filesystem"
442 " this early\n", filename
);
447 pathname
= linker_search_path(filename
);
448 if (pathname
== NULL
)
451 error
= nlookup_init(&nd
, pathname
, UIO_SYSSPACE
, NLC_FOLLOW
|NLC_LOCKVP
);
453 error
= vn_open(&nd
, NULL
, FREAD
, 0);
454 kfree(pathname
, M_LINKER
);
460 nd
.nl_open_vp
= NULL
;
464 * Read the elf header from the file.
466 firstpage
= kmalloc(PAGE_SIZE
, M_LINKER
, M_WAITOK
);
467 hdr
= (Elf_Ehdr
*)firstpage
;
468 error
= vn_rdwr(UIO_READ
, vp
, firstpage
, PAGE_SIZE
, 0,
469 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
470 nbytes
= PAGE_SIZE
- resid
;
479 if (hdr
->e_ident
[EI_CLASS
] != ELF_TARG_CLASS
480 || hdr
->e_ident
[EI_DATA
] != ELF_TARG_DATA
) {
481 link_elf_error("Unsupported file layout");
485 if (hdr
->e_ident
[EI_VERSION
] != EV_CURRENT
486 || hdr
->e_version
!= EV_CURRENT
) {
487 link_elf_error("Unsupported file version");
491 if (hdr
->e_type
!= ET_EXEC
&& hdr
->e_type
!= ET_DYN
) {
495 if (hdr
->e_machine
!= ELF_TARG_MACH
) {
496 link_elf_error("Unsupported machine");
502 * We rely on the program header being in the first page. This is
503 * not strictly required by the ABI specification, but it seems to
504 * always true in practice. And, it simplifies things considerably.
506 if (!((hdr
->e_phentsize
== sizeof(Elf_Phdr
)) &&
507 (hdr
->e_phoff
+ hdr
->e_phnum
*sizeof(Elf_Phdr
) <= PAGE_SIZE
) &&
508 (hdr
->e_phoff
+ hdr
->e_phnum
*sizeof(Elf_Phdr
) <= nbytes
)))
509 link_elf_error("Unreadable program headers");
512 * Scan the program header entries, and save key information.
514 * We rely on there being exactly two load segments, text and data,
517 phdr
= (Elf_Phdr
*) (firstpage
+ hdr
->e_phoff
);
518 phlimit
= phdr
+ hdr
->e_phnum
;
522 while (phdr
< phlimit
) {
523 switch (phdr
->p_type
) {
527 link_elf_error("Too many sections");
551 link_elf_error("Object is not dynamically-linked");
557 * Allocate the entire address space of the object, to stake out our
558 * contiguous region, and to establish the base address for relocation.
560 base_offset
= trunc_page(segs
[0]->p_offset
);
561 base_vaddr
= trunc_page(segs
[0]->p_vaddr
);
562 base_vlimit
= round_page(segs
[1]->p_vaddr
+ segs
[1]->p_memsz
);
563 mapsize
= base_vlimit
- base_vaddr
;
565 ef
= kmalloc(sizeof(struct elf_file
), M_LINKER
, M_WAITOK
| M_ZERO
);
566 #ifdef SPARSE_MAPPING
567 ef
->object
= vm_object_allocate(OBJT_DEFAULT
, mapsize
>> PAGE_SHIFT
);
568 if (ef
->object
== NULL
) {
573 vm_object_reference(ef
->object
);
574 ef
->address
= (caddr_t
)vm_map_min(&kernel_map
);
575 error
= vm_map_find(&kernel_map
, ef
->object
, 0,
576 (vm_offset_t
*)&ef
->address
,
578 1, VM_MAPTYPE_NORMAL
,
579 VM_PROT_ALL
, VM_PROT_ALL
,
582 vm_object_deallocate(ef
->object
);
587 ef
->address
= kmalloc(mapsize
, M_LINKER
, M_WAITOK
);
589 mapbase
= ef
->address
;
592 * Read the text and data sections and zero the bss.
594 for (i
= 0; i
< 2; i
++) {
595 caddr_t segbase
= mapbase
+ segs
[i
]->p_vaddr
- base_vaddr
;
596 error
= vn_rdwr(UIO_READ
, vp
,
597 segbase
, segs
[i
]->p_filesz
, segs
[i
]->p_offset
,
598 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
600 #ifdef SPARSE_MAPPING
601 vm_map_remove(&kernel_map
, (vm_offset_t
) ef
->address
,
602 (vm_offset_t
) ef
->address
603 + (ef
->object
->size
<< PAGE_SHIFT
));
604 vm_object_deallocate(ef
->object
);
606 kfree(ef
->address
, M_LINKER
);
611 bzero(segbase
+ segs
[i
]->p_filesz
,
612 segs
[i
]->p_memsz
- segs
[i
]->p_filesz
);
614 #ifdef SPARSE_MAPPING
616 * Wire down the pages
618 vm_map_wire(&kernel_map
,
619 (vm_offset_t
) segbase
,
620 (vm_offset_t
) segbase
+ segs
[i
]->p_memsz
,
625 ef
->dynamic
= (const Elf_Dyn
*) (mapbase
+ phdyn
->p_vaddr
- base_vaddr
);
627 lf
= linker_make_file(filename
, ef
, &link_elf_file_ops
);
629 #ifdef SPARSE_MAPPING
630 vm_map_remove(&kernel_map
, (vm_offset_t
) ef
->address
,
631 (vm_offset_t
) ef
->address
632 + (ef
->object
->size
<< PAGE_SHIFT
));
633 vm_object_deallocate(ef
->object
);
635 kfree(ef
->address
, M_LINKER
);
641 lf
->address
= ef
->address
;
644 error
= parse_dynamic(lf
);
647 link_elf_reloc_local(lf
);
648 error
= linker_load_dependencies(lf
);
651 error
= relocate_file(lf
);
655 /* Try and load the symbol table if it's present. (you can strip it!) */
656 nbytes
= hdr
->e_shnum
* hdr
->e_shentsize
;
657 if (nbytes
== 0 || hdr
->e_shoff
== 0)
659 shdr
= kmalloc(nbytes
, M_LINKER
, M_WAITOK
| M_ZERO
);
660 error
= vn_rdwr(UIO_READ
, vp
,
661 (caddr_t
)shdr
, nbytes
, hdr
->e_shoff
,
662 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
667 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
668 if (shdr
[i
].sh_type
== SHT_SYMTAB
) {
670 symstrindex
= shdr
[i
].sh_link
;
673 if (symtabindex
< 0 || symstrindex
< 0)
676 symcnt
= shdr
[symtabindex
].sh_size
;
677 ef
->symbase
= kmalloc(symcnt
, M_LINKER
, M_WAITOK
);
678 strcnt
= shdr
[symstrindex
].sh_size
;
679 ef
->strbase
= kmalloc(strcnt
, M_LINKER
, M_WAITOK
);
680 error
= vn_rdwr(UIO_READ
, vp
,
681 ef
->symbase
, symcnt
, shdr
[symtabindex
].sh_offset
,
682 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
685 error
= vn_rdwr(UIO_READ
, vp
,
686 ef
->strbase
, strcnt
, shdr
[symstrindex
].sh_offset
,
687 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
);
691 ef
->ddbsymcnt
= symcnt
/ sizeof(Elf_Sym
);
692 ef
->ddbsymtab
= (const Elf_Sym
*)ef
->symbase
;
693 ef
->ddbstrcnt
= strcnt
;
694 ef
->ddbstrtab
= ef
->strbase
;
702 linker_file_unload(lf
);
704 kfree(shdr
, M_LINKER
);
706 kfree(firstpage
, M_LINKER
);
714 elf_relocaddr(linker_file_t lf
, Elf_Addr x
)
720 if (x
>= ef
->pcpu_start
&& x
< ef
->pcpu_stop
)
721 return ((x
- ef
->pcpu_start
) + ef
->pcpu_base
);
723 if (x
>= ef
->vnet_start
&& x
< ef
->vnet_stop
)
724 return ((x
- ef
->vnet_start
) + ef
->vnet_base
);
731 link_elf_unload_file(linker_file_t file
)
733 elf_file_t ef
= file
->priv
;
736 #ifdef SPARSE_MAPPING
738 vm_map_remove(&kernel_map
, (vm_offset_t
) ef
->address
,
739 (vm_offset_t
) ef
->address
740 + (ef
->object
->size
<< PAGE_SHIFT
));
741 vm_object_deallocate(ef
->object
);
745 kfree(ef
->address
, M_LINKER
);
748 kfree(ef
->symbase
, M_LINKER
);
750 kfree(ef
->strbase
, M_LINKER
);
756 link_elf_unload_module(linker_file_t file
)
758 elf_file_t ef
= file
->priv
;
763 preload_delete_name(file
->filename
);
767 symbol_name(elf_file_t ef
, Elf_Size r_info
)
771 if (ELF_R_SYM(r_info
)) {
772 ref
= ef
->symtab
+ ELF_R_SYM(r_info
);
773 return ef
->strtab
+ ref
->st_name
;
779 relocate_file(linker_file_t lf
)
781 elf_file_t ef
= lf
->priv
;
782 const Elf_Rel
*rellim
;
784 const Elf_Rela
*relalim
;
785 const Elf_Rela
*rela
;
788 /* Perform relocations without addend if there are any: */
791 rellim
= (const Elf_Rel
*)((const char *)ef
->rel
+ ef
->relsize
);
792 while (rel
< rellim
) {
793 if (elf_reloc(lf
, (Elf_Addr
)ef
->address
, rel
, ELF_RELOC_REL
, elf_lookup
)) {
794 symname
= symbol_name(ef
, rel
->r_info
);
795 kprintf("link_elf: symbol %s undefined\n", symname
);
802 /* Perform relocations with addend if there are any: */
805 relalim
= (const Elf_Rela
*)((const char *)ef
->rela
+ ef
->relasize
);
806 while (rela
< relalim
) {
807 if (elf_reloc(lf
, (Elf_Addr
)ef
->address
, rela
, ELF_RELOC_RELA
, elf_lookup
)) {
808 symname
= symbol_name(ef
, rela
->r_info
);
809 kprintf("link_elf: symbol %s undefined\n", symname
);
816 /* Perform PLT relocations without addend if there are any: */
819 rellim
= (const Elf_Rel
*)((const char *)ef
->pltrel
+ ef
->pltrelsize
);
820 while (rel
< rellim
) {
821 if (elf_reloc(lf
, (Elf_Addr
)ef
->address
, rel
, ELF_RELOC_REL
, elf_lookup
)) {
822 symname
= symbol_name(ef
, rel
->r_info
);
823 kprintf("link_elf: symbol %s undefined\n", symname
);
830 /* Perform relocations with addend if there are any: */
833 relalim
= (const Elf_Rela
*)((const char *)ef
->pltrela
+ ef
->pltrelasize
);
834 while (rela
< relalim
) {
835 symname
= symbol_name(ef
, rela
->r_info
);
836 if (elf_reloc(lf
, (Elf_Addr
)ef
->address
, rela
, ELF_RELOC_RELA
, elf_lookup
)) {
837 kprintf("link_elf: symbol %s undefined\n", symname
);
848 * Hash function for symbol table lookup. Don't even think about changing
849 * this. It is specified by the System V ABI.
852 elf_hash(const char *name
)
854 const unsigned char *p
= (const unsigned char *) name
;
860 if ((g
= h
& 0xf0000000) != 0)
868 link_elf_lookup_symbol(linker_file_t lf
, const char* name
, c_linker_sym_t
* sym
)
870 elf_file_t ef
= lf
->priv
;
871 unsigned long symnum
;
877 /* If we don't have a hash, bail. */
878 if (ef
->buckets
== NULL
|| ef
->nbuckets
== 0) {
879 kprintf("link_elf_lookup_symbol: missing symbol hash table\n");
883 /* First, search hashed global symbols */
884 hash
= elf_hash(name
);
885 symnum
= ef
->buckets
[hash
% ef
->nbuckets
];
887 while (symnum
!= STN_UNDEF
) {
888 if (symnum
>= ef
->nchains
) {
889 kprintf("link_elf_lookup_symbol: corrupt symbol table\n");
893 symp
= ef
->symtab
+ symnum
;
894 if (symp
->st_name
== 0) {
895 kprintf("link_elf_lookup_symbol: corrupt symbol table\n");
899 strp
= ef
->strtab
+ symp
->st_name
;
901 if (strcmp(name
, strp
) == 0) {
902 if (symp
->st_shndx
!= SHN_UNDEF
||
903 (symp
->st_value
!= 0 &&
904 ELF_ST_TYPE(symp
->st_info
) == STT_FUNC
)
906 *sym
= (c_linker_sym_t
) symp
;
913 symnum
= ef
->chains
[symnum
];
916 /* If we have not found it, look at the full table (if loaded) */
917 if (ef
->symtab
== ef
->ddbsymtab
)
920 /* Exhaustive search */
921 for (i
= 0, symp
= ef
->ddbsymtab
; i
< ef
->ddbsymcnt
; i
++, symp
++) {
922 strp
= ef
->ddbstrtab
+ symp
->st_name
;
923 if (strcmp(name
, strp
) == 0) {
924 if (symp
->st_shndx
!= SHN_UNDEF
||
925 (symp
->st_value
!= 0 &&
926 ELF_ST_TYPE(symp
->st_info
) == STT_FUNC
)) {
927 *sym
= (c_linker_sym_t
) symp
;
938 link_elf_symbol_values(linker_file_t lf
, c_linker_sym_t sym
, linker_symval_t
*symval
)
940 elf_file_t ef
= lf
->priv
;
941 const Elf_Sym
*es
= (const Elf_Sym
*)sym
;
943 if (es
>= ef
->symtab
&& ((es
- ef
->symtab
) < ef
->nchains
)) {
944 symval
->name
= ef
->strtab
+ es
->st_name
;
945 symval
->value
= (caddr_t
) ef
->address
+ es
->st_value
;
946 symval
->size
= es
->st_size
;
949 if (ef
->symtab
== ef
->ddbsymtab
)
951 if (es
>= ef
->ddbsymtab
&& ((es
- ef
->ddbsymtab
) < ef
->ddbsymcnt
)) {
952 symval
->name
= ef
->ddbstrtab
+ es
->st_name
;
953 symval
->value
= (caddr_t
) ef
->address
+ es
->st_value
;
954 symval
->size
= es
->st_size
;
961 link_elf_search_symbol(linker_file_t lf
, caddr_t value
,
962 c_linker_sym_t
*sym
, long *diffp
)
964 elf_file_t ef
= lf
->priv
;
965 u_long off
= (uintptr_t)(void *)value
;
969 const Elf_Sym
*best
= 0;
972 for (i
= 0, es
= ef
->ddbsymtab
; i
< ef
->ddbsymcnt
; i
++, es
++) {
973 if (es
->st_name
== 0)
975 st_value
= es
->st_value
+ (uintptr_t)(void *)ef
->address
;
976 if (off
>= st_value
) {
977 if (off
- st_value
< diff
) {
978 diff
= off
- st_value
;
982 } else if (off
- st_value
== diff
) {
991 *sym
= (c_linker_sym_t
) best
;
997 * Look up a linker set on an ELF system.
1000 link_elf_lookup_set(linker_file_t lf
, const char *name
,
1001 void ***startp
, void ***stopp
, int *countp
)
1004 linker_symval_t symval
;
1006 void **start
, **stop
;
1007 int len
, error
= 0, count
;
1009 len
= strlen(name
) + sizeof("__start_set_"); /* sizeof includes \0 */
1010 setsym
= kmalloc(len
, M_LINKER
, M_WAITOK
);
1012 /* get address of first entry */
1013 ksnprintf(setsym
, len
, "%s%s", "__start_set_", name
);
1014 error
= link_elf_lookup_symbol(lf
, setsym
, &sym
);
1017 link_elf_symbol_values(lf
, sym
, &symval
);
1018 if (symval
.value
== 0) {
1022 start
= (void **)symval
.value
;
1024 /* get address of last entry */
1025 ksnprintf(setsym
, len
, "%s%s", "__stop_set_", name
);
1026 error
= link_elf_lookup_symbol(lf
, setsym
, &sym
);
1029 link_elf_symbol_values(lf
, sym
, &symval
);
1030 if (symval
.value
== 0) {
1034 stop
= (void **)symval
.value
;
1036 /* and the number of entries */
1037 count
= stop
- start
;
1048 kfree(setsym
, M_LINKER
);
1053 * Symbol lookup function that can be used when the symbol index is known (ie
1054 * in relocations). It uses the symbol index instead of doing a fully fledged
1055 * hash table based lookup when such is valid. For example for local symbols.
1056 * This is not only more efficient, it's also more correct. It's not always
1057 * the case that the symbol can be found through the hash table.
1060 elf_lookup(linker_file_t lf
, Elf_Size symidx
, int deps
, Elf_Addr
*result
)
1062 elf_file_t ef
= lf
->priv
;
1066 /* Don't even try to lookup the symbol if the index is bogus. */
1067 if (symidx
>= ef
->nchains
)
1070 sym
= ef
->symtab
+ symidx
;
1073 * Don't do a full lookup when the symbol is local. It may even
1074 * fail because it may not be found through the hash table.
1076 if (ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
) {
1077 /* Force lookup failure when we have an insanity. */
1078 if (sym
->st_shndx
== SHN_UNDEF
|| sym
->st_value
== 0)
1080 return ((Elf_Addr
) ef
->address
+ sym
->st_value
);
1083 * XXX we can avoid doing a hash table based lookup for global
1084 * symbols as well. This however is not always valid, so we'll
1085 * just do it the hard way for now. Performance tweaks can
1089 symbol
= ef
->strtab
+ sym
->st_name
;
1091 /* Force a lookup failure if the symbol name is bogus. */
1095 return (linker_file_lookup_symbol(lf
, symbol
, deps
, (caddr_t
*)result
));
1098 link_elf_reloc_local(linker_file_t lf
)
1100 elf_file_t ef
= lf
->priv
;
1101 const Elf_Rel
*rellim
;
1103 const Elf_Rela
*relalim
;
1104 const Elf_Rela
*rela
;
1106 /* Perform relocations without addend if there are any: */
1107 if ((rel
= ef
->rel
) != NULL
) {
1108 rellim
= (const Elf_Rel
*)((const char *)ef
->rel
+ ef
->relsize
);
1109 while (rel
< rellim
) {
1110 elf_reloc_local(lf
, (Elf_Addr
)ef
->address
, rel
, ELF_RELOC_REL
,
1116 /* Perform relocations with addend if there are any: */
1117 if ((rela
= ef
->rela
) != NULL
) {
1118 relalim
= (const Elf_Rela
*)((const char *)ef
->rela
+ ef
->relasize
);
1119 while (rela
< relalim
) {
1120 elf_reloc_local(lf
, (Elf_Addr
)ef
->address
, rela
, ELF_RELOC_RELA
,