2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * Copyright (c) 1998 Peter Wemm <peter@freebsd.org>
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/boot/common/load_elf.c,v 1.29 2003/08/25 23:30:41 obrien Exp $
28 * $DragonFly: src/sys/boot/common/load_elf.c,v 1.7 2008/09/02 17:21:12 dillon Exp $
31 #include <sys/param.h>
33 #include <sys/linker.h>
34 #include <sys/module.h>
36 #include <machine/elf.h>
41 #include "bootstrap.h"
43 #define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l)
45 #if defined(__i386__) && __ELF_WORD_SIZE == 64
48 #define ELF_TARG_CLASS ELFCLASS64
49 #define ELF_TARG_MACH EM_X86_64
52 typedef struct elf_file
{
72 static int __elfN(loadimage
)(struct preloaded_file
*mp
, elf_file_t ef
, u_int64_t loadaddr
);
73 static int __elfN(lookup_symbol
)(struct preloaded_file
*mp
, elf_file_t ef
, const char* name
, Elf_Sym
* sym
);
75 static void __elfN(reloc_ptr
)(struct preloaded_file
*mp
, elf_file_t ef
,
76 void *p
, void *val
, size_t len
);
78 static int __elfN(parse_modmetadata
)(struct preloaded_file
*mp
, elf_file_t ef
);
79 static char *fake_modname(const char *name
);
81 const char *__elfN(kerneltype
) = "elf kernel";
82 const char *__elfN(moduletype
) = "elf module";
85 * Attempt to load the file (file) as an ELF module. It will be stored at
86 * (dest), and a pointer to a module structure describing the loaded object
87 * will be saved in (result).
90 __elfN(loadfile
)(char *filename
, u_int64_t dest
, struct preloaded_file
**result
)
92 struct preloaded_file
*fp
, *kfp
;
100 bzero(&ef
, sizeof(struct elf_file
));
103 * Open the image, read and validate the ELF header
105 if (filename
== NULL
) /* can't handle nameless */
107 if ((ef
.fd
= rel_open(filename
, O_RDONLY
)) == -1)
109 ef
.firstpage
= malloc(PAGE_SIZE
);
110 if (ef
.firstpage
== NULL
) {
114 bytes_read
= read(ef
.fd
, ef
.firstpage
, PAGE_SIZE
);
115 ef
.firstlen
= (size_t)bytes_read
;
116 if (bytes_read
< 0 || ef
.firstlen
<= sizeof(Elf_Ehdr
)) {
117 err
= EFTYPE
; /* could be EIO, but may be small file */
120 ehdr
= ef
.ehdr
= (Elf_Ehdr
*)ef
.firstpage
;
123 if (!IS_ELF(*ehdr
)) {
127 if (ehdr
->e_ident
[EI_CLASS
] != ELF_TARG_CLASS
|| /* Layout ? */
128 ehdr
->e_ident
[EI_DATA
] != ELF_TARG_DATA
||
129 ehdr
->e_ident
[EI_VERSION
] != EV_CURRENT
|| /* Version ? */
130 ehdr
->e_version
!= EV_CURRENT
||
131 ehdr
->e_machine
!= ELF_TARG_MACH
) { /* Machine ? */
138 * Check to see what sort of module we are.
140 kfp
= file_findfile(NULL
, NULL
);
141 if (ehdr
->e_type
== ET_DYN
) {
142 /* Looks like a kld module */
144 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: can't load module before kernel\n");
148 if (strcmp(__elfN(kerneltype
), kfp
->f_type
)) {
149 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: can't load module with kernel type '%s'\n", kfp
->f_type
);
153 /* Looks OK, got ahead */
156 /* Page-align the load address */
157 pad
= (u_int
)dest
& PAGE_MASK
;
159 pad
= PAGE_SIZE
- pad
;
162 } else if (ehdr
->e_type
== ET_EXEC
) {
163 /* Looks like a kernel */
165 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: kernel already loaded\n");
170 * Calculate destination address based on kernel entrypoint
172 dest
= ehdr
->e_entry
;
174 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: not a kernel (maybe static binary?)\n");
186 * Ok, we think we should handle this.
190 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: cannot allocate module info\n");
195 setenv("kernelname", filename
, 1);
196 fp
->f_name
= strdup(filename
);
197 fp
->f_type
= strdup(ef
.kernel
? __elfN(kerneltype
) : __elfN(moduletype
));
201 printf("%s entry at 0x%jx\n", filename
, (uintmax_t)dest
);
203 printf("%s ", filename
);
206 fp
->f_size
= __elfN(loadimage
)(fp
, &ef
, dest
);
207 if (fp
->f_size
== 0 || fp
->f_addr
== 0)
210 /* save exec header as metadata */
211 file_addmetadata(fp
, MODINFOMD_ELFHDR
, sizeof(*ehdr
), ehdr
);
213 /* Load OK, return module pointer */
214 *result
= (struct preloaded_file
*)fp
;
230 * With the file (fd) open on the image, and (ehdr) containing
231 * the Elf header, load the image at (off)
234 __elfN(loadimage
)(struct preloaded_file
*fp
, elf_file_t ef
, u_int64_t off
)
239 Elf_Phdr
*phdr
, *php
;
242 vm_offset_t firstaddr
;
243 vm_offset_t lastaddr
;
260 firstaddr
= lastaddr
= 0;
264 #if __ELF_WORD_SIZE == 64
265 off
= - (off
& 0xffffffffff000000ull
);/* x86_64 relocates after locore */
267 off
= - (off
& 0xff000000u
); /* i386 relocates after locore */
273 if ((ehdr
->e_phoff
+ ehdr
->e_phnum
* sizeof(*phdr
)) > ef
->firstlen
) {
274 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadimage: program header not within first page\n");
277 phdr
= (Elf_Phdr
*)(ef
->firstpage
+ ehdr
->e_phoff
);
279 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
280 /* We want to load PT_LOAD segments only.. */
281 if (phdr
[i
].p_type
!= PT_LOAD
)
285 printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx",
286 (long)phdr
[i
].p_filesz
, (long)phdr
[i
].p_offset
,
287 (long)(phdr
[i
].p_vaddr
+ off
),
288 (long)(phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_memsz
- 1));
290 if ((phdr
[i
].p_flags
& PF_W
) == 0) {
291 printf("text=0x%lx ", (long)phdr
[i
].p_filesz
);
293 printf("data=0x%lx", (long)phdr
[i
].p_filesz
);
294 if (phdr
[i
].p_filesz
< phdr
[i
].p_memsz
)
295 printf("+0x%lx", (long)(phdr
[i
].p_memsz
-phdr
[i
].p_filesz
));
300 if (ef
->firstlen
> phdr
[i
].p_offset
) {
301 fpcopy
= ef
->firstlen
- phdr
[i
].p_offset
;
302 archsw
.arch_copyin(ef
->firstpage
+ phdr
[i
].p_offset
,
303 phdr
[i
].p_vaddr
+ off
, fpcopy
);
305 if (phdr
[i
].p_filesz
> fpcopy
) {
306 if (lseek(ef
->fd
, (off_t
)(phdr
[i
].p_offset
+ fpcopy
),
308 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
) "_loadexec: cannot seek\n");
311 if (archsw
.arch_readin(ef
->fd
, phdr
[i
].p_vaddr
+ off
+ fpcopy
,
312 phdr
[i
].p_filesz
- fpcopy
) != (ssize_t
)(phdr
[i
].p_filesz
- fpcopy
)) {
313 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
) "_loadexec: archsw.readin failed\n");
317 /* clear space from oversized segments; eg: bss */
318 if (phdr
[i
].p_filesz
< phdr
[i
].p_memsz
) {
320 printf(" (bss: 0x%lx-0x%lx)",
321 (long)(phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_filesz
),
322 (long)(phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_memsz
- 1));
325 /* no archsw.arch_bzero */
326 buf
= malloc(PAGE_SIZE
);
328 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
) "_loadimage: malloc() failed\n");
331 bzero(buf
, PAGE_SIZE
);
332 resid
= phdr
[i
].p_memsz
- phdr
[i
].p_filesz
;
333 dest
= phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_filesz
;
335 chunk
= min(PAGE_SIZE
, resid
);
336 archsw
.arch_copyin(buf
, dest
, chunk
);
346 if (firstaddr
== 0 || firstaddr
> (phdr
[i
].p_vaddr
+ off
))
347 firstaddr
= phdr
[i
].p_vaddr
+ off
;
348 if (lastaddr
== 0 || lastaddr
< (phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_memsz
))
349 lastaddr
= phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_memsz
;
351 lastaddr
= roundup(lastaddr
, sizeof(long));
354 * Now grab the symbol tables. This isn't easy if we're reading a
355 * .gz file. I think the rule is going to have to be that you must
356 * strip a file to remove symbols before gzipping it so that we do not
357 * try to lseek() on it.
359 chunk
= ehdr
->e_shnum
* ehdr
->e_shentsize
;
360 if (chunk
== 0 || ehdr
->e_shoff
== 0)
362 shdr
= malloc(chunk
);
365 if (lseek(ef
->fd
, (off_t
)ehdr
->e_shoff
, SEEK_SET
) == -1) {
366 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
) "_loadimage: cannot lseek() to section headers");
369 result
= read(ef
->fd
, shdr
, chunk
);
370 if (result
< 0 || (size_t)result
!= chunk
) {
371 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
) "_loadimage: read section headers failed");
376 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
377 if (shdr
[i
].sh_type
!= SHT_SYMTAB
)
379 for (j
= 0; j
< ehdr
->e_phnum
; j
++) {
380 if (phdr
[j
].p_type
!= PT_LOAD
)
382 if (shdr
[i
].sh_offset
>= phdr
[j
].p_offset
&&
383 (shdr
[i
].sh_offset
+ shdr
[i
].sh_size
<=
384 phdr
[j
].p_offset
+ phdr
[j
].p_filesz
)) {
385 shdr
[i
].sh_offset
= 0;
390 if (shdr
[i
].sh_offset
== 0 || shdr
[i
].sh_size
== 0)
391 continue; /* alread loaded in a PT_LOAD above */
392 /* Save it for loading below */
394 symstrindex
= shdr
[i
].sh_link
;
396 if (symtabindex
< 0 || symstrindex
< 0)
399 /* Ok, committed to a load. */
404 for (i
= symtabindex
; i
>= 0; i
= symstrindex
) {
408 switch(shdr
[i
].sh_type
) {
409 case SHT_SYMTAB
: /* Symbol table */
412 case SHT_STRTAB
: /* String table */
421 size
= shdr
[i
].sh_size
;
422 archsw
.arch_copyin(&size
, lastaddr
, sizeof(size
));
423 lastaddr
+= sizeof(size
);
426 printf("\n%s: 0x%lx@0x%lx -> 0x%lx-0x%lx", secname
,
427 shdr
[i
].sh_size
, shdr
[i
].sh_offset
,
428 lastaddr
, lastaddr
+ shdr
[i
].sh_size
);
430 if (i
== symstrindex
)
432 printf("0x%lx+0x%lx", (long)sizeof(size
), (long)size
);
435 if (lseek(ef
->fd
, (off_t
)shdr
[i
].sh_offset
, SEEK_SET
) == -1) {
436 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
) "_loadimage: could not seek for symbols - skipped!");
441 result
= archsw
.arch_readin(ef
->fd
, lastaddr
, shdr
[i
].sh_size
);
442 if (result
< 0 || (size_t)result
!= shdr
[i
].sh_size
) {
443 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
) "_loadimage: could not read symbols - skipped!");
448 /* Reset offsets relative to ssym */
449 lastaddr
+= shdr
[i
].sh_size
;
450 lastaddr
= roundup(lastaddr
, sizeof(size
));
451 if (i
== symtabindex
)
453 else if (i
== symstrindex
)
461 file_addmetadata(fp
, MODINFOMD_SSYM
, sizeof(ssym
), &ssym
);
462 file_addmetadata(fp
, MODINFOMD_ESYM
, sizeof(esym
), &esym
);
467 ret
= lastaddr
- firstaddr
;
468 fp
->f_addr
= firstaddr
;
471 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
472 if (phdr
[i
].p_type
== PT_DYNAMIC
) {
475 file_addmetadata(fp
, MODINFOMD_DYNAMIC
, sizeof(adp
), &adp
);
480 if (php
== NULL
) /* this is bad, we cannot get to symbols or _DYNAMIC */
483 ndp
= php
->p_filesz
/ sizeof(Elf_Dyn
);
486 dp
= malloc(php
->p_filesz
);
489 archsw
.arch_copyout(php
->p_vaddr
+ off
, dp
, php
->p_filesz
);
492 for (i
= 0; i
< ndp
; i
++) {
493 if (dp
[i
].d_tag
== 0)
495 switch (dp
[i
].d_tag
) {
497 ef
->hashtab
= (Elf_Hashelt
*)(uintptr_t)(dp
[i
].d_un
.d_ptr
+ off
);
500 ef
->strtab
= (char *)(uintptr_t)(dp
[i
].d_un
.d_ptr
+ off
);
503 ef
->strsz
= dp
[i
].d_un
.d_val
;
506 ef
->symtab
= (Elf_Sym
*)(uintptr_t)(dp
[i
].d_un
.d_ptr
+ off
);
509 ef
->rela
= (Elf_Rela
*)(uintptr_t)(dp
[i
].d_un
.d_ptr
+ off
);
512 ef
->relasz
= dp
[i
].d_un
.d_val
;
518 if (ef
->hashtab
== NULL
|| ef
->symtab
== NULL
||
519 ef
->strtab
== NULL
|| ef
->strsz
== 0)
521 COPYOUT(ef
->hashtab
, &ef
->nbuckets
, sizeof(ef
->nbuckets
));
522 COPYOUT(ef
->hashtab
+ 1, &ef
->nchains
, sizeof(ef
->nchains
));
523 ef
->buckets
= ef
->hashtab
+ 2;
524 ef
->chains
= ef
->buckets
+ ef
->nbuckets
;
525 if (__elfN(parse_modmetadata
)(fp
, ef
) == 0)
528 if (ef
->kernel
) /* kernel must not depend on anything */
539 static char invalid_name
[] = "bad";
542 fake_modname(const char *name
)
548 sp
= strrchr(name
, '/');
553 ep
= strrchr(name
, '.');
557 ep
= invalid_name
+ sizeof(invalid_name
) - 1;
560 ep
= name
+ strlen(name
);
562 fp
= malloc(len
+ 1);
570 #if defined(__i386__) && __ELF_WORD_SIZE == 64
571 struct mod_metadata64
{
572 int md_version
; /* structure version MDTV_* */
573 int md_type
; /* type of entry MDT_* */
574 u_int64_t md_data
; /* specific data */
575 u_int64_t md_cval
; /* common string label */
580 __elfN(parse_modmetadata
)(struct preloaded_file
*fp
, elf_file_t ef
)
582 struct mod_metadata md
;
583 #if defined(__i386__) && __ELF_WORD_SIZE == 64
584 struct mod_metadata64 md64
;
586 struct mod_depend
*mdepend
;
587 struct mod_version mver
;
590 int modcnt
, minfolen
;
591 Elf_Addr v
, p
, p_stop
;
593 if (__elfN(lookup_symbol
)(fp
, ef
, "__start_set_modmetadata_set", &sym
) != 0)
595 p
= sym
.st_value
+ ef
->off
;
596 if (__elfN(lookup_symbol
)(fp
, ef
, "__stop_set_modmetadata_set", &sym
) != 0)
598 p_stop
= sym
.st_value
+ ef
->off
;
602 COPYOUT(p
, &v
, sizeof(v
));
604 __elfN(reloc_ptr
)(fp
, ef
, p
, &v
, sizeof(v
));
608 #if defined(__i386__) && __ELF_WORD_SIZE == 64
609 COPYOUT(v
, &md64
, sizeof(md64
));
610 md
.md_version
= md64
.md_version
;
611 md
.md_type
= md64
.md_type
;
612 md
.md_cval
= (const char *)(uintptr_t)(md64
.md_cval
+ ef
->off
);
613 md
.md_data
= (void *)(uintptr_t)(md64
.md_data
+ ef
->off
);
615 COPYOUT(v
, &md
, sizeof(md
));
617 __elfN(reloc_ptr
)(fp
, ef
, v
, &md
, sizeof(md
));
619 md
.md_cval
+= ef
->off
;
620 md
.md_data
= (uint8_t *)md
.md_data
+ ef
->off
;
623 p
+= sizeof(Elf_Addr
);
626 if (ef
->kernel
) /* kernel must not depend on anything */
628 s
= strdupout((vm_offset_t
)md
.md_cval
);
629 minfolen
= sizeof(*mdepend
) + strlen(s
) + 1;
630 mdepend
= malloc(minfolen
);
633 COPYOUT((vm_offset_t
)md
.md_data
, mdepend
, sizeof(*mdepend
));
634 strcpy((char*)(mdepend
+ 1), s
);
636 file_addmetadata(fp
, MODINFOMD_DEPLIST
, minfolen
, mdepend
);
640 s
= strdupout((vm_offset_t
)md
.md_cval
);
641 COPYOUT((vm_offset_t
)md
.md_data
, &mver
, sizeof(mver
));
642 file_addmodule(fp
, s
, mver
.mv_version
, NULL
);
649 s
= fake_modname(fp
->f_name
);
650 file_addmodule(fp
, s
, 1, NULL
);
657 elf_hash(const char *name
)
659 const unsigned char *p
= (const unsigned char *) name
;
665 if ((g
= h
& 0xf0000000) != 0)
672 static const char __elfN(bad_symtable
)[] = "elf" __XSTRING(__ELF_WORD_SIZE
) "_lookup_symbol: corrupt symbol table\n";
674 __elfN(lookup_symbol
)(struct preloaded_file
*fp
, elf_file_t ef
, const char* name
,
682 hash
= elf_hash(name
);
683 COPYOUT(&ef
->buckets
[hash
% ef
->nbuckets
], &symnum
, sizeof(symnum
));
685 while (symnum
!= STN_UNDEF
) {
686 if (symnum
>= ef
->nchains
) {
687 printf(__elfN(bad_symtable
));
691 COPYOUT(ef
->symtab
+ symnum
, &sym
, sizeof(sym
));
692 if (sym
.st_name
== 0) {
693 printf(__elfN(bad_symtable
));
697 strp
= strdupout((vm_offset_t
)(ef
->strtab
+ sym
.st_name
));
698 if (strcmp(name
, strp
) == 0) {
700 if (sym
.st_shndx
!= SHN_UNDEF
||
701 (sym
.st_value
!= 0 &&
702 ELF_ST_TYPE(sym
.st_info
) == STT_FUNC
)) {
709 COPYOUT(&ef
->chains
[symnum
], &symnum
, sizeof(symnum
));
716 * Apply any intra-module relocations to the value. *p is the load address
717 * of the value and val/len is the value to be modified. This does NOT modify
718 * the image in-place, because this is done by kern_linker later on.
721 __elfN(reloc_ptr
)(struct preloaded_file
*mp
, elf_file_t ef
,
722 void *p
, void *val
, size_t len
)
724 Elf_Addr off
= (Elf_Addr
)p
- ef
->off
, word
;
728 for (n
= 0; n
< ef
->relasz
/ sizeof(r
); n
++) {
729 COPYOUT(ef
->rela
+ n
, &r
, sizeof(r
));
731 if (r
.r_offset
>= off
&& r
.r_offset
< off
+ len
&&
732 ELF_R_TYPE(r
.r_info
) == R_SPARC_RELATIVE
) {
733 word
= ef
->off
+ r
.r_addend
;
734 bcopy(&word
, (char *)val
+ (r
.r_offset
- off
),