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.17 2005/03/04 00:01:30 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 static int link_elf_load_module(const char*, linker_file_t
*);
54 static int link_elf_load_file(const char*, linker_file_t
*);
55 static int link_elf_lookup_symbol(linker_file_t
, const char*,
57 static int link_elf_symbol_values(linker_file_t
, c_linker_sym_t
, linker_symval_t
*);
58 static int link_elf_search_symbol(linker_file_t
, caddr_t value
,
59 c_linker_sym_t
* sym
, long* diffp
);
61 static void link_elf_unload_file(linker_file_t
);
62 static void link_elf_unload_module(linker_file_t
);
63 static int link_elf_lookup_set(linker_file_t
, const char *,
64 void ***, void ***, int *);
66 static struct linker_class_ops link_elf_class_ops
= {
70 static struct linker_file_ops link_elf_file_ops
= {
71 link_elf_lookup_symbol
,
72 link_elf_symbol_values
,
73 link_elf_search_symbol
,
78 static struct linker_file_ops link_elf_module_ops
= {
79 link_elf_lookup_symbol
,
80 link_elf_symbol_values
,
81 link_elf_search_symbol
,
82 link_elf_unload_module
,
86 typedef struct elf_file
{
87 caddr_t address
; /* Relocation address */
89 vm_object_t object
; /* VM object to hold file pages */
91 const Elf_Dyn
* dynamic
; /* Symbol table etc. */
92 Elf_Off nbuckets
; /* DT_HASH info */
94 const Elf_Off
* buckets
;
95 const Elf_Off
* chains
;
97 caddr_t strtab
; /* DT_STRTAB */
98 int strsz
; /* DT_STRSZ */
99 const Elf_Sym
* symtab
; /* DT_SYMTAB */
100 Elf_Addr
* got
; /* DT_PLTGOT */
101 const Elf_Rel
* pltrel
; /* DT_JMPREL */
102 int pltrelsize
; /* DT_PLTRELSZ */
103 const Elf_Rela
* pltrela
; /* DT_JMPREL */
104 int pltrelasize
; /* DT_PLTRELSZ */
105 const Elf_Rel
* rel
; /* DT_REL */
106 int relsize
; /* DT_RELSZ */
107 const Elf_Rela
* rela
; /* DT_RELA */
108 int relasize
; /* DT_RELASZ */
110 const Elf_Sym
* ddbsymtab
; /* The symbol table we are using */
111 long ddbsymcnt
; /* Number of symbols */
112 caddr_t ddbstrtab
; /* String table */
113 long ddbstrcnt
; /* number of bytes in string table */
114 caddr_t symbase
; /* malloc'ed symbold base */
115 caddr_t strbase
; /* malloc'ed string base */
118 static int parse_dynamic(linker_file_t lf
);
119 static int load_dependancies(linker_file_t lf
);
120 static int relocate_file(linker_file_t lf
);
121 static int parse_module_symbols(linker_file_t lf
);
124 * The kernel symbol table starts here.
126 extern struct _dynamic _DYNAMIC
;
129 link_elf_init(void* arg
)
132 caddr_t modptr
, baseptr
, sizeptr
;
136 #if ELF_TARG_CLASS == ELFCLASS32
137 linker_add_class("elf32", NULL
, &link_elf_class_ops
);
139 linker_add_class("elf64", NULL
, &link_elf_class_ops
);
142 dp
= (Elf_Dyn
*) &_DYNAMIC
;
144 ef
= malloc(sizeof(struct elf_file
), M_LINKER
, M_INTWAIT
| M_ZERO
);
146 #ifdef SPARSE_MAPPING
151 modptr
= preload_search_by_type("elf kernel");
153 modname
= (char *)preload_search_info(modptr
, MODINFO_NAME
);
156 linker_kernel_file
= linker_make_file(modname
, ef
, &link_elf_file_ops
);
157 if (linker_kernel_file
== NULL
)
158 panic("link_elf_init: Can't create linker structures for kernel");
159 parse_dynamic(linker_kernel_file
);
160 linker_kernel_file
->address
= (caddr_t
) KERNBASE
;
161 linker_kernel_file
->size
= -(intptr_t)linker_kernel_file
->address
;
165 baseptr
= preload_search_info(modptr
, MODINFO_ADDR
);
167 linker_kernel_file
->address
= *(caddr_t
*)baseptr
;
168 sizeptr
= preload_search_info(modptr
, MODINFO_SIZE
);
170 linker_kernel_file
->size
= *(size_t *)sizeptr
;
172 parse_module_symbols(linker_kernel_file
);
173 linker_current_file
= linker_kernel_file
;
174 linker_kernel_file
->flags
|= LINKER_FILE_LINKED
;
178 SYSINIT(link_elf
, SI_SUB_KLD
, SI_ORDER_SECOND
, link_elf_init
, 0);
181 parse_module_symbols(linker_file_t lf
)
183 elf_file_t ef
= lf
->priv
;
185 caddr_t ssym
, esym
, base
;
191 if (ef
->modptr
== NULL
)
193 pointer
= preload_search_info(ef
->modptr
, MODINFO_METADATA
|MODINFOMD_SSYM
);
196 ssym
= *(caddr_t
*)pointer
;
197 pointer
= preload_search_info(ef
->modptr
, MODINFO_METADATA
|MODINFOMD_ESYM
);
200 esym
= *(caddr_t
*)pointer
;
204 symcnt
= *(long *)base
;
205 base
+= sizeof(long);
206 symtab
= (Elf_Sym
*)base
;
207 base
+= roundup(symcnt
, sizeof(long));
209 if (base
> esym
|| base
< ssym
) {
210 printf("Symbols are corrupt!\n");
214 strcnt
= *(long *)base
;
215 base
+= sizeof(long);
217 base
+= roundup(strcnt
, sizeof(long));
219 if (base
> esym
|| base
< ssym
) {
220 printf("Symbols are corrupt!\n");
224 ef
->ddbsymtab
= symtab
;
225 ef
->ddbsymcnt
= symcnt
/ sizeof(Elf_Sym
);
226 ef
->ddbstrtab
= strtab
;
227 ef
->ddbstrcnt
= strcnt
;
233 parse_dynamic(linker_file_t lf
)
235 elf_file_t ef
= lf
->priv
;
237 int plttype
= DT_REL
;
239 for (dp
= ef
->dynamic
; dp
->d_tag
!= DT_NULL
; dp
++) {
243 /* From src/libexec/rtld-elf/rtld.c */
244 const Elf_Off
*hashtab
= (const Elf_Off
*)
245 (ef
->address
+ dp
->d_un
.d_ptr
);
246 ef
->nbuckets
= hashtab
[0];
247 ef
->nchains
= hashtab
[1];
248 ef
->buckets
= hashtab
+ 2;
249 ef
->chains
= ef
->buckets
+ ef
->nbuckets
;
253 ef
->strtab
= (caddr_t
) (ef
->address
+ dp
->d_un
.d_ptr
);
256 ef
->strsz
= dp
->d_un
.d_val
;
259 ef
->symtab
= (Elf_Sym
*) (ef
->address
+ dp
->d_un
.d_ptr
);
262 if (dp
->d_un
.d_val
!= sizeof(Elf_Sym
))
266 ef
->got
= (Elf_Addr
*) (ef
->address
+ dp
->d_un
.d_ptr
);
269 ef
->rel
= (const Elf_Rel
*) (ef
->address
+ dp
->d_un
.d_ptr
);
272 ef
->relsize
= dp
->d_un
.d_val
;
275 if (dp
->d_un
.d_val
!= sizeof(Elf_Rel
))
279 ef
->pltrel
= (const Elf_Rel
*) (ef
->address
+ dp
->d_un
.d_ptr
);
282 ef
->pltrelsize
= dp
->d_un
.d_val
;
285 ef
->rela
= (const Elf_Rela
*) (ef
->address
+ dp
->d_un
.d_ptr
);
288 ef
->relasize
= dp
->d_un
.d_val
;
291 if (dp
->d_un
.d_val
!= sizeof(Elf_Rela
))
295 plttype
= dp
->d_un
.d_val
;
296 if (plttype
!= DT_REL
&& plttype
!= DT_RELA
)
302 if (plttype
== DT_RELA
) {
303 ef
->pltrela
= (const Elf_Rela
*) ef
->pltrel
;
305 ef
->pltrelasize
= ef
->pltrelsize
;
309 ef
->ddbsymtab
= ef
->symtab
;
310 ef
->ddbsymcnt
= ef
->nchains
;
311 ef
->ddbstrtab
= ef
->strtab
;
312 ef
->ddbstrcnt
= ef
->strsz
;
318 link_elf_error(const char *s
)
320 printf("kldload: %s\n", s
);
324 link_elf_load_module(const char *filename
, linker_file_t
*result
)
326 caddr_t modptr
, baseptr
, sizeptr
, dynptr
;
334 * Look to see if we have the module preloaded.
336 modptr
= preload_search_by_name(filename
);
338 return (link_elf_load_file(filename
, result
));
340 /* It's preloaded, check we can handle it and collect information */
341 type
= (char *)preload_search_info(modptr
, MODINFO_TYPE
);
342 baseptr
= preload_search_info(modptr
, MODINFO_ADDR
);
343 sizeptr
= preload_search_info(modptr
, MODINFO_SIZE
);
344 dynptr
= preload_search_info(modptr
, MODINFO_METADATA
|MODINFOMD_DYNAMIC
);
345 if (type
== NULL
|| strcmp(type
, "elf module") != 0)
347 if (baseptr
== NULL
|| sizeptr
== NULL
|| dynptr
== NULL
)
350 ef
= malloc(sizeof(struct elf_file
), M_LINKER
, M_WAITOK
| M_ZERO
);
354 ef
->address
= *(caddr_t
*)baseptr
;
355 #ifdef SPARSE_MAPPING
358 dp
= (vm_offset_t
)ef
->address
+ *(vm_offset_t
*)dynptr
;
359 ef
->dynamic
= (Elf_Dyn
*)dp
;
360 lf
= linker_make_file(filename
, ef
, &link_elf_module_ops
);
365 lf
->address
= ef
->address
;
366 lf
->size
= *(size_t *)sizeptr
;
368 error
= parse_dynamic(lf
);
370 linker_file_unload(lf
);
373 error
= load_dependancies(lf
);
375 linker_file_unload(lf
);
378 error
= relocate_file(lf
);
380 linker_file_unload(lf
);
383 parse_module_symbols(lf
);
384 lf
->flags
|= LINKER_FILE_LINKED
;
390 link_elf_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
;
409 Elf_Addr base_vlimit
;
422 if (p
->p_ucred
== NULL
) {
423 printf("link_elf_load_file: cannot load '%s' from filesystem"
424 " 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 free(pathname
, M_LINKER
);
442 nd
.nl_open_vp
= NULL
;
446 * Read the elf header from the file.
448 firstpage
= malloc(PAGE_SIZE
, M_LINKER
, M_WAITOK
);
449 if (firstpage
== NULL
) {
453 hdr
= (Elf_Ehdr
*)firstpage
;
454 error
= vn_rdwr(UIO_READ
, vp
, firstpage
, PAGE_SIZE
, 0,
455 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
, td
);
456 nbytes
= PAGE_SIZE
- resid
;
465 if (hdr
->e_ident
[EI_CLASS
] != ELF_TARG_CLASS
466 || hdr
->e_ident
[EI_DATA
] != ELF_TARG_DATA
) {
467 link_elf_error("Unsupported file layout");
471 if (hdr
->e_ident
[EI_VERSION
] != EV_CURRENT
472 || hdr
->e_version
!= EV_CURRENT
) {
473 link_elf_error("Unsupported file version");
477 if (hdr
->e_type
!= ET_EXEC
&& hdr
->e_type
!= ET_DYN
) {
478 link_elf_error("Unsupported file type");
482 if (hdr
->e_machine
!= ELF_TARG_MACH
) {
483 link_elf_error("Unsupported machine");
489 * We rely on the program header being in the first page. This is
490 * not strictly required by the ABI specification, but it seems to
491 * always true in practice. And, it simplifies things considerably.
493 if (!((hdr
->e_phentsize
== sizeof(Elf_Phdr
)) &&
494 (hdr
->e_phoff
+ hdr
->e_phnum
*sizeof(Elf_Phdr
) <= PAGE_SIZE
) &&
495 (hdr
->e_phoff
+ hdr
->e_phnum
*sizeof(Elf_Phdr
) <= nbytes
)))
496 link_elf_error("Unreadable program headers");
499 * Scan the program header entries, and save key information.
501 * We rely on there being exactly two load segments, text and data,
504 phdr
= (Elf_Phdr
*) (firstpage
+ hdr
->e_phoff
);
505 phlimit
= phdr
+ hdr
->e_phnum
;
509 while (phdr
< phlimit
) {
510 switch (phdr
->p_type
) {
514 link_elf_error("Too many sections");
534 link_elf_error("Object is not dynamically-linked");
540 * Allocate the entire address space of the object, to stake out our
541 * contiguous region, and to establish the base address for relocation.
543 base_offset
= trunc_page(segs
[0]->p_offset
);
544 base_vaddr
= trunc_page(segs
[0]->p_vaddr
);
545 base_vlimit
= round_page(segs
[1]->p_vaddr
+ segs
[1]->p_memsz
);
546 mapsize
= base_vlimit
- base_vaddr
;
548 ef
= malloc(sizeof(struct elf_file
), M_LINKER
, M_WAITOK
| M_ZERO
);
549 #ifdef SPARSE_MAPPING
550 ef
->object
= vm_object_allocate(OBJT_DEFAULT
, mapsize
>> PAGE_SHIFT
);
551 if (ef
->object
== NULL
) {
556 vm_object_reference(ef
->object
);
557 ef
->address
= (caddr_t
) vm_map_min(kernel_map
);
558 error
= vm_map_find(kernel_map
, ef
->object
, 0,
559 (vm_offset_t
*) &ef
->address
,
561 VM_PROT_ALL
, VM_PROT_ALL
, 0);
563 vm_object_deallocate(ef
->object
);
568 ef
->address
= malloc(mapsize
, M_LINKER
, M_WAITOK
);
570 mapbase
= ef
->address
;
573 * Read the text and data sections and zero the bss.
575 for (i
= 0; i
< 2; i
++) {
576 caddr_t segbase
= mapbase
+ segs
[i
]->p_vaddr
- base_vaddr
;
577 error
= vn_rdwr(UIO_READ
, vp
,
578 segbase
, segs
[i
]->p_filesz
, segs
[i
]->p_offset
,
579 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
, td
);
581 #ifdef SPARSE_MAPPING
582 vm_map_remove(kernel_map
, (vm_offset_t
) ef
->address
,
583 (vm_offset_t
) ef
->address
584 + (ef
->object
->size
<< PAGE_SHIFT
));
585 vm_object_deallocate(ef
->object
);
587 free(ef
->address
, M_LINKER
);
592 bzero(segbase
+ segs
[i
]->p_filesz
,
593 segs
[i
]->p_memsz
- segs
[i
]->p_filesz
);
595 #ifdef SPARSE_MAPPING
597 * Wire down the pages
599 vm_map_wire(kernel_map
,
600 (vm_offset_t
) segbase
,
601 (vm_offset_t
) segbase
+ segs
[i
]->p_memsz
,
606 ef
->dynamic
= (const Elf_Dyn
*) (mapbase
+ phdyn
->p_vaddr
- base_vaddr
);
608 lf
= linker_make_file(filename
, ef
, &link_elf_file_ops
);
610 #ifdef SPARSE_MAPPING
611 vm_map_remove(kernel_map
, (vm_offset_t
) ef
->address
,
612 (vm_offset_t
) ef
->address
613 + (ef
->object
->size
<< PAGE_SHIFT
));
614 vm_object_deallocate(ef
->object
);
616 free(ef
->address
, M_LINKER
);
622 lf
->address
= ef
->address
;
625 error
= parse_dynamic(lf
);
628 error
= load_dependancies(lf
);
631 error
= relocate_file(lf
);
635 /* Try and load the symbol table if it's present. (you can strip it!) */
636 nbytes
= hdr
->e_shnum
* hdr
->e_shentsize
;
637 if (nbytes
== 0 || hdr
->e_shoff
== 0)
639 shdr
= malloc(nbytes
, M_LINKER
, M_WAITOK
| M_ZERO
);
644 error
= vn_rdwr(UIO_READ
, vp
,
645 (caddr_t
)shdr
, nbytes
, hdr
->e_shoff
,
646 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
, td
);
651 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
652 if (shdr
[i
].sh_type
== SHT_SYMTAB
) {
654 symstrindex
= shdr
[i
].sh_link
;
657 if (symtabindex
< 0 || symstrindex
< 0)
660 symcnt
= shdr
[symtabindex
].sh_size
;
661 ef
->symbase
= malloc(symcnt
, M_LINKER
, M_WAITOK
);
662 strcnt
= shdr
[symstrindex
].sh_size
;
663 ef
->strbase
= malloc(strcnt
, M_LINKER
, M_WAITOK
);
665 if (ef
->symbase
== NULL
|| ef
->strbase
== NULL
) {
669 error
= vn_rdwr(UIO_READ
, vp
,
670 ef
->symbase
, symcnt
, shdr
[symtabindex
].sh_offset
,
671 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
, td
);
674 error
= vn_rdwr(UIO_READ
, vp
,
675 ef
->strbase
, strcnt
, shdr
[symstrindex
].sh_offset
,
676 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
, td
);
680 ef
->ddbsymcnt
= symcnt
/ sizeof(Elf_Sym
);
681 ef
->ddbsymtab
= (const Elf_Sym
*)ef
->symbase
;
682 ef
->ddbstrcnt
= strcnt
;
683 ef
->ddbstrtab
= ef
->strbase
;
685 lf
->flags
|= LINKER_FILE_LINKED
;
693 linker_file_unload(lf
);
695 free(shdr
, M_LINKER
);
697 free(firstpage
, M_LINKER
);
698 VOP_UNLOCK(vp
, 0, td
);
699 vn_close(vp
, FREAD
, td
);
705 link_elf_unload_file(linker_file_t file
)
707 elf_file_t ef
= file
->priv
;
710 #ifdef SPARSE_MAPPING
712 vm_map_remove(kernel_map
, (vm_offset_t
) ef
->address
,
713 (vm_offset_t
) ef
->address
714 + (ef
->object
->size
<< PAGE_SHIFT
));
715 vm_object_deallocate(ef
->object
);
719 free(ef
->address
, M_LINKER
);
722 free(ef
->symbase
, M_LINKER
);
724 free(ef
->strbase
, M_LINKER
);
730 link_elf_unload_module(linker_file_t file
)
732 elf_file_t ef
= file
->priv
;
737 preload_delete_name(file
->filename
);
741 load_dependancies(linker_file_t lf
)
743 elf_file_t ef
= lf
->priv
;
750 * All files are dependant on /kernel.
752 if (linker_kernel_file
) {
753 linker_kernel_file
->refs
++;
754 linker_file_add_dependancy(lf
, linker_kernel_file
);
757 for (dp
= ef
->dynamic
; dp
->d_tag
!= DT_NULL
; dp
++) {
758 if (dp
->d_tag
== DT_NEEDED
) {
759 name
= ef
->strtab
+ dp
->d_un
.d_val
;
761 error
= linker_load_file(name
, &lfdep
);
764 error
= linker_file_add_dependancy(lf
, lfdep
);
775 symbol_name(elf_file_t ef
, Elf_Word r_info
)
779 if (ELF_R_SYM(r_info
)) {
780 ref
= ef
->symtab
+ ELF_R_SYM(r_info
);
781 return ef
->strtab
+ ref
->st_name
;
787 relocate_file(linker_file_t lf
)
789 elf_file_t ef
= lf
->priv
;
790 const Elf_Rel
*rellim
;
792 const Elf_Rela
*relalim
;
793 const Elf_Rela
*rela
;
796 /* Perform relocations without addend if there are any: */
799 rellim
= (const Elf_Rel
*)((const char *)ef
->rel
+ ef
->relsize
);
800 while (rel
< rellim
) {
801 symname
= symbol_name(ef
, rel
->r_info
);
802 if (elf_reloc(lf
, rel
, ELF_RELOC_REL
, symname
)) {
803 printf("link_elf: symbol %s undefined\n", symname
);
810 /* Perform relocations with addend if there are any: */
813 relalim
= (const Elf_Rela
*)((const char *)ef
->rela
+ ef
->relasize
);
814 while (rela
< relalim
) {
815 symname
= symbol_name(ef
, rela
->r_info
);
816 if (elf_reloc(lf
, rela
, ELF_RELOC_RELA
, symname
)) {
817 printf("link_elf: symbol %s undefined\n", symname
);
824 /* Perform PLT relocations without addend if there are any: */
827 rellim
= (const Elf_Rel
*)((const char *)ef
->pltrel
+ ef
->pltrelsize
);
828 while (rel
< rellim
) {
829 symname
= symbol_name(ef
, rel
->r_info
);
830 if (elf_reloc(lf
, rel
, ELF_RELOC_REL
, symname
)) {
831 printf("link_elf: symbol %s undefined\n", symname
);
838 /* Perform relocations with addend if there are any: */
841 relalim
= (const Elf_Rela
*)((const char *)ef
->pltrela
+ ef
->pltrelasize
);
842 while (rela
< relalim
) {
843 symname
= symbol_name(ef
, rela
->r_info
);
844 if (elf_reloc(lf
, rela
, ELF_RELOC_RELA
, symname
)) {
845 printf("link_elf: symbol %s undefined\n", symname
);
856 * Hash function for symbol table lookup. Don't even think about changing
857 * this. It is specified by the System V ABI.
860 elf_hash(const char *name
)
862 const unsigned char *p
= (const unsigned char *) name
;
868 if ((g
= h
& 0xf0000000) != 0)
876 link_elf_lookup_symbol(linker_file_t lf
, const char* name
, c_linker_sym_t
* sym
)
878 elf_file_t ef
= lf
->priv
;
879 unsigned long symnum
;
885 /* First, search hashed global symbols */
886 hash
= elf_hash(name
);
887 symnum
= ef
->buckets
[hash
% ef
->nbuckets
];
889 while (symnum
!= STN_UNDEF
) {
890 if (symnum
>= ef
->nchains
) {
891 printf("link_elf_lookup_symbol: corrupt symbol table\n");
895 symp
= ef
->symtab
+ symnum
;
896 if (symp
->st_name
== 0) {
897 printf("link_elf_lookup_symbol: corrupt symbol table\n");
901 strp
= ef
->strtab
+ symp
->st_name
;
903 if (strcmp(name
, strp
) == 0) {
904 if (symp
->st_shndx
!= SHN_UNDEF
||
905 (symp
->st_value
!= 0 &&
906 ELF_ST_TYPE(symp
->st_info
) == STT_FUNC
)
908 *sym
= (c_linker_sym_t
) symp
;
915 symnum
= ef
->chains
[symnum
];
918 /* If we have not found it, look at the full table (if loaded) */
919 if (ef
->symtab
== ef
->ddbsymtab
)
922 /* Exhaustive search */
923 for (i
= 0, symp
= ef
->ddbsymtab
; i
< ef
->ddbsymcnt
; i
++, symp
++) {
924 strp
= ef
->ddbstrtab
+ symp
->st_name
;
925 if (strcmp(name
, strp
) == 0) {
926 if (symp
->st_shndx
!= SHN_UNDEF
||
927 (symp
->st_value
!= 0 &&
928 ELF_ST_TYPE(symp
->st_info
) == STT_FUNC
)) {
929 *sym
= (c_linker_sym_t
) symp
;
940 link_elf_symbol_values(linker_file_t lf
, c_linker_sym_t sym
, linker_symval_t
* symval
)
942 elf_file_t ef
= lf
->priv
;
943 const Elf_Sym
* es
= (const Elf_Sym
*) sym
;
945 if (es
>= ef
->symtab
&& ((es
- ef
->symtab
) < ef
->nchains
)) {
946 symval
->name
= ef
->strtab
+ es
->st_name
;
947 symval
->value
= (caddr_t
) ef
->address
+ es
->st_value
;
948 symval
->size
= es
->st_size
;
951 if (ef
->symtab
== ef
->ddbsymtab
)
953 if (es
>= ef
->ddbsymtab
&& ((es
- ef
->ddbsymtab
) < ef
->ddbsymcnt
)) {
954 symval
->name
= ef
->ddbstrtab
+ es
->st_name
;
955 symval
->value
= (caddr_t
) ef
->address
+ es
->st_value
;
956 symval
->size
= es
->st_size
;
963 link_elf_search_symbol(linker_file_t lf
, caddr_t value
,
964 c_linker_sym_t
* sym
, long* diffp
)
966 elf_file_t ef
= lf
->priv
;
967 u_long off
= (uintptr_t) (void *) value
;
971 const Elf_Sym
* best
= 0;
974 for (i
= 0, es
= ef
->ddbsymtab
; i
< ef
->ddbsymcnt
; i
++, es
++) {
975 if (es
->st_name
== 0)
977 st_value
= es
->st_value
+ (uintptr_t) (void *) ef
->address
;
978 if (off
>= st_value
) {
979 if (off
- st_value
< diff
) {
980 diff
= off
- st_value
;
984 } else if (off
- st_value
== diff
) {
993 *sym
= (c_linker_sym_t
) best
;
999 * Look up a linker set on an ELF system.
1002 link_elf_lookup_set(linker_file_t lf
, const char *name
,
1003 void ***startp
, void ***stopp
, int *countp
)
1006 linker_symval_t symval
;
1008 void **start
, **stop
;
1009 int len
, error
= 0, count
;
1011 len
= strlen(name
) + sizeof("__start_set_"); /* sizeof includes \0 */
1012 setsym
= malloc(len
, M_LINKER
, M_WAITOK
);
1016 /* get address of first entry */
1017 snprintf(setsym
, len
, "%s%s", "__start_set_", name
);
1018 error
= link_elf_lookup_symbol(lf
, setsym
, &sym
);
1021 link_elf_symbol_values(lf
, sym
, &symval
);
1022 if (symval
.value
== 0) {
1026 start
= (void **)symval
.value
;
1028 /* get address of last entry */
1029 snprintf(setsym
, len
, "%s%s", "__stop_set_", name
);
1030 error
= link_elf_lookup_symbol(lf
, setsym
, &sym
);
1033 link_elf_symbol_values(lf
, sym
, &symval
);
1034 if (symval
.value
== 0) {
1038 stop
= (void **)symval
.value
;
1040 /* and the number of entries */
1041 count
= stop
- start
;
1052 free(setsym
, M_LINKER
);