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.39 2008/10/14 10:11:14 raj Exp $
30 #include <sys/param.h>
32 #include <sys/linker.h>
33 #include <sys/module.h>
34 #include <sys/stdint.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
{
74 static int __elfN(loadimage
)(struct preloaded_file
*mp
, elf_file_t ef
, u_int64_t loadaddr
);
75 static int __elfN(lookup_symbol
)(struct preloaded_file
*mp
, elf_file_t ef
, const char* name
, Elf_Sym
* sym
);
76 static int __elfN(reloc_ptr
)(struct preloaded_file
*mp
, elf_file_t ef
,
77 Elf_Addr p
, void *val
, size_t len
);
78 static int __elfN(parse_modmetadata
)(struct preloaded_file
*mp
, elf_file_t ef
);
79 static symaddr_fn
__elfN(symaddr
);
80 static char *fake_modname(const char *name
);
82 const char *__elfN(kerneltype
) = "elf kernel";
83 const char *__elfN(moduletype
) = "elf module";
85 u_int64_t
__elfN(relocation_offset
) = 0;
88 * Attempt to load the file (file) as an ELF module. It will be stored at
89 * (dest), and a pointer to a module structure describing the loaded object
90 * will be saved in (result).
93 __elfN(loadfile
)(char *filename
, u_int64_t dest
, struct preloaded_file
**result
)
95 struct preloaded_file
*fp
, *kfp
;
103 bzero(&ef
, sizeof(struct elf_file
));
106 * Open the image, read and validate the ELF header
108 if (filename
== NULL
) /* can't handle nameless */
110 if ((ef
.fd
= rel_open(filename
, O_RDONLY
)) == -1)
112 ef
.firstpage
= malloc(PAGE_SIZE
);
113 if (ef
.firstpage
== NULL
) {
117 bytes_read
= read(ef
.fd
, ef
.firstpage
, PAGE_SIZE
);
118 ef
.firstlen
= (size_t)bytes_read
;
119 if (bytes_read
< 0 || ef
.firstlen
<= sizeof(Elf_Ehdr
)) {
120 err
= EFTYPE
; /* could be EIO, but may be small file */
123 ehdr
= ef
.ehdr
= (Elf_Ehdr
*)ef
.firstpage
;
126 if (!IS_ELF(*ehdr
)) {
130 if (ehdr
->e_ident
[EI_CLASS
] != ELF_TARG_CLASS
|| /* Layout ? */
131 ehdr
->e_ident
[EI_DATA
] != ELF_TARG_DATA
||
132 ehdr
->e_ident
[EI_VERSION
] != EV_CURRENT
|| /* Version ? */
133 ehdr
->e_version
!= EV_CURRENT
||
134 ehdr
->e_machine
!= ELF_TARG_MACH
) { /* Machine ? */
141 * Check to see what sort of module we are.
143 kfp
= file_findfile(NULL
, NULL
);
144 if (ehdr
->e_type
== ET_DYN
) {
145 /* Looks like a kld module */
147 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: can't load module before kernel\n");
151 if (strcmp(__elfN(kerneltype
), kfp
->f_type
)) {
152 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: can't load module with kernel type '%s'\n", kfp
->f_type
);
156 /* Looks OK, got ahead */
159 /* Page-align the load address */
160 pad
= (u_int
)dest
& PAGE_MASK
;
162 pad
= PAGE_SIZE
- pad
;
165 } else if (ehdr
->e_type
== ET_EXEC
) {
166 /* Looks like a kernel */
168 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: kernel already loaded\n");
173 * Calculate destination address based on kernel entrypoint
175 dest
= ehdr
->e_entry
;
177 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: not a kernel (maybe static binary?)\n");
189 * Ok, we think we should handle this.
193 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadfile: cannot allocate module info\n");
198 setenv("kernelname", filename
, 1);
199 fp
->f_name
= strdup(filename
);
200 fp
->f_type
= strdup(ef
.kernel
? __elfN(kerneltype
) : __elfN(moduletype
));
204 printf("%s entry at 0x%jx\n", filename
, (uintmax_t)dest
);
206 printf("%s ", filename
);
209 fp
->f_size
= __elfN(loadimage
)(fp
, &ef
, dest
);
210 if (fp
->f_size
== 0 || fp
->f_addr
== 0)
213 /* save exec header as metadata */
214 file_addmetadata(fp
, MODINFOMD_ELFHDR
, sizeof(*ehdr
), ehdr
);
216 /* Load OK, return module pointer */
217 *result
= (struct preloaded_file
*)fp
;
233 * With the file (fd) open on the image, and (ehdr) containing
234 * the Elf header, load the image at (off)
237 __elfN(loadimage
)(struct preloaded_file
*fp
, elf_file_t ef
, u_int64_t off
)
242 Elf_Phdr
*phdr
, *php
;
245 vm_offset_t firstaddr
;
246 vm_offset_t lastaddr
;
261 firstaddr
= lastaddr
= 0;
265 #if __ELF_WORD_SIZE == 64
266 off
= - (off
& 0xffffffffff000000ull
);/* x86_64 relocates after locore */
268 off
= - (off
& 0xff000000u
); /* i386 relocates after locore */
270 #elif defined(__powerpc__)
272 * On the purely virtual memory machines like e500, the kernel is
273 * linked against its final VA range, which is most often not
274 * available at the loader stage, but only after kernel initializes
275 * and completes its VM settings. In such cases we cannot use p_vaddr
276 * field directly to load ELF segments, but put them at some
277 * 'load-time' locations.
279 if (off
& 0xf0000000u
) {
280 off
= -(off
& 0xf0000000u
);
282 * XXX the physical load address should not be hardcoded. Note
283 * that the Book-E kernel assumes that it's loaded at a 16MB
284 * boundary for now...
287 ehdr
->e_entry
+= off
;
289 printf("Converted entry 0x%08x\n", ehdr
->e_entry
);
293 #elif defined(__arm__)
294 if (off
& 0xf0000000u
) {
295 off
= -(off
& 0xf0000000u
);
296 ehdr
->e_entry
+= off
;
298 printf("Converted entry 0x%08x\n", ehdr
->e_entry
);
303 off
= 0; /* other archs use direct mapped kernels */
305 __elfN(relocation_offset
) = off
;
309 if ((ehdr
->e_phoff
+ ehdr
->e_phnum
* sizeof(*phdr
)) > ef
->firstlen
) {
310 printf("elf" __XSTRING(__ELF_WORD_SIZE
) "_loadimage: program header not within first page\n");
313 phdr
= (Elf_Phdr
*)(ef
->firstpage
+ ehdr
->e_phoff
);
315 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
316 /* We want to load PT_LOAD segments only.. */
317 if (phdr
[i
].p_type
!= PT_LOAD
)
321 printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx",
322 (long)phdr
[i
].p_filesz
, (long)phdr
[i
].p_offset
,
323 (long)(phdr
[i
].p_vaddr
+ off
),
324 (long)(phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_memsz
- 1));
326 if ((phdr
[i
].p_flags
& PF_W
) == 0) {
327 printf("text=0x%lx ", (long)phdr
[i
].p_filesz
);
329 printf("data=0x%lx", (long)phdr
[i
].p_filesz
);
330 if (phdr
[i
].p_filesz
< phdr
[i
].p_memsz
)
331 printf("+0x%lx", (long)(phdr
[i
].p_memsz
-phdr
[i
].p_filesz
));
336 if (ef
->firstlen
> phdr
[i
].p_offset
) {
337 fpcopy
= ef
->firstlen
- phdr
[i
].p_offset
;
338 archsw
.arch_copyin(ef
->firstpage
+ phdr
[i
].p_offset
,
339 phdr
[i
].p_vaddr
+ off
, fpcopy
);
341 if (phdr
[i
].p_filesz
> fpcopy
) {
342 if (kern_pread(ef
->fd
, phdr
[i
].p_vaddr
+ off
+ fpcopy
,
343 phdr
[i
].p_filesz
- fpcopy
, phdr
[i
].p_offset
+ fpcopy
) != 0) {
344 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
)
345 "_loadimage: read failed\n");
349 /* clear space from oversized segments; eg: bss */
350 if (phdr
[i
].p_filesz
< phdr
[i
].p_memsz
) {
352 printf(" (bss: 0x%lx-0x%lx)",
353 (long)(phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_filesz
),
354 (long)(phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_memsz
- 1));
357 kern_bzero(phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_filesz
,
358 phdr
[i
].p_memsz
- phdr
[i
].p_filesz
);
364 if (firstaddr
== 0 || firstaddr
> (phdr
[i
].p_vaddr
+ off
))
365 firstaddr
= phdr
[i
].p_vaddr
+ off
;
366 if (lastaddr
== 0 || lastaddr
< (phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_memsz
))
367 lastaddr
= phdr
[i
].p_vaddr
+ off
+ phdr
[i
].p_memsz
;
369 lastaddr
= roundup(lastaddr
, sizeof(long));
372 * Now grab the symbol tables. This isn't easy if we're reading a
373 * .gz file. I think the rule is going to have to be that you must
374 * strip a file to remove symbols before gzipping it so that we do not
375 * try to lseek() on it.
377 chunk
= ehdr
->e_shnum
* ehdr
->e_shentsize
;
378 if (chunk
== 0 || ehdr
->e_shoff
== 0)
380 shdr
= alloc_pread(ef
->fd
, ehdr
->e_shoff
, chunk
);
382 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
)
383 "_loadimage: failed to read section headers");
388 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
389 if (shdr
[i
].sh_type
!= SHT_SYMTAB
)
391 for (j
= 0; j
< ehdr
->e_phnum
; j
++) {
392 if (phdr
[j
].p_type
!= PT_LOAD
)
394 if (shdr
[i
].sh_offset
>= phdr
[j
].p_offset
&&
395 (shdr
[i
].sh_offset
+ shdr
[i
].sh_size
<=
396 phdr
[j
].p_offset
+ phdr
[j
].p_filesz
)) {
397 shdr
[i
].sh_offset
= 0;
402 if (shdr
[i
].sh_offset
== 0 || shdr
[i
].sh_size
== 0)
403 continue; /* alread loaded in a PT_LOAD above */
404 /* Save it for loading below */
406 symstrindex
= shdr
[i
].sh_link
;
408 if (symtabindex
< 0 || symstrindex
< 0)
411 /* Ok, committed to a load. */
416 for (i
= symtabindex
; i
>= 0; i
= symstrindex
) {
420 switch(shdr
[i
].sh_type
) {
421 case SHT_SYMTAB
: /* Symbol table */
424 case SHT_STRTAB
: /* String table */
433 size
= shdr
[i
].sh_size
;
434 archsw
.arch_copyin(&size
, lastaddr
, sizeof(size
));
435 lastaddr
+= sizeof(size
);
438 printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname
,
439 (uintmax_t)shdr
[i
].sh_size
, (uintmax_t)shdr
[i
].sh_offset
,
440 (uintmax_t)lastaddr
, (uintmax_t)(lastaddr
+ shdr
[i
].sh_size
));
442 if (i
== symstrindex
)
444 printf("0x%lx+0x%lx", (long)sizeof(size
), (long)size
);
447 if (lseek(ef
->fd
, (off_t
)shdr
[i
].sh_offset
, SEEK_SET
) == -1) {
448 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
) "_loadimage: could not seek for symbols - skipped!");
453 result
= archsw
.arch_readin(ef
->fd
, lastaddr
, shdr
[i
].sh_size
);
454 if (result
< 0 || (size_t)result
!= shdr
[i
].sh_size
) {
455 printf("\nelf" __XSTRING(__ELF_WORD_SIZE
) "_loadimage: could not read symbols - skipped!");
460 /* Reset offsets relative to ssym */
461 lastaddr
+= shdr
[i
].sh_size
;
462 lastaddr
= roundup(lastaddr
, sizeof(size
));
463 if (i
== symtabindex
)
465 else if (i
== symstrindex
)
473 file_addmetadata(fp
, MODINFOMD_SSYM
, sizeof(ssym
), &ssym
);
474 file_addmetadata(fp
, MODINFOMD_ESYM
, sizeof(esym
), &esym
);
479 ret
= lastaddr
- firstaddr
;
480 fp
->f_addr
= firstaddr
;
483 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
484 if (phdr
[i
].p_type
== PT_DYNAMIC
) {
487 file_addmetadata(fp
, MODINFOMD_DYNAMIC
, sizeof(adp
), &adp
);
492 if (php
== NULL
) /* this is bad, we cannot get to symbols or _DYNAMIC */
495 ndp
= php
->p_filesz
/ sizeof(Elf_Dyn
);
498 dp
= malloc(php
->p_filesz
);
501 archsw
.arch_copyout(php
->p_vaddr
+ off
, dp
, php
->p_filesz
);
504 for (i
= 0; i
< ndp
; i
++) {
505 if (dp
[i
].d_tag
== 0)
507 switch (dp
[i
].d_tag
) {
509 ef
->hashtab
= (Elf_Hashelt
*)(uintptr_t)(dp
[i
].d_un
.d_ptr
+ off
);
512 ef
->strtab
= (char *)(uintptr_t)(dp
[i
].d_un
.d_ptr
+ off
);
515 ef
->strsz
= dp
[i
].d_un
.d_val
;
518 ef
->symtab
= (Elf_Sym
*)(uintptr_t)(dp
[i
].d_un
.d_ptr
+ off
);
521 ef
->rel
= (Elf_Rel
*)(uintptr_t)(dp
[i
].d_un
.d_ptr
+ off
);
524 ef
->relsz
= dp
[i
].d_un
.d_val
;
527 ef
->rela
= (Elf_Rela
*)(uintptr_t)(dp
[i
].d_un
.d_ptr
+ off
);
530 ef
->relasz
= dp
[i
].d_un
.d_val
;
536 if (ef
->hashtab
== NULL
|| ef
->symtab
== NULL
||
537 ef
->strtab
== NULL
|| ef
->strsz
== 0)
539 COPYOUT(ef
->hashtab
, &ef
->nbuckets
, sizeof(ef
->nbuckets
));
540 COPYOUT(ef
->hashtab
+ 1, &ef
->nchains
, sizeof(ef
->nchains
));
541 ef
->buckets
= ef
->hashtab
+ 2;
542 ef
->chains
= ef
->buckets
+ ef
->nbuckets
;
543 if (__elfN(parse_modmetadata
)(fp
, ef
) == 0)
546 if (ef
->kernel
) /* kernel must not depend on anything */
557 static char invalid_name
[] = "bad";
560 fake_modname(const char *name
)
566 sp
= strrchr(name
, '/');
571 ep
= strrchr(name
, '.');
575 ep
= invalid_name
+ sizeof(invalid_name
) - 1;
578 ep
= name
+ strlen(name
);
580 fp
= malloc(len
+ 1);
588 #if defined(__i386__) && __ELF_WORD_SIZE == 64
589 struct mod_metadata64
{
590 int md_version
; /* structure version MDTV_* */
591 int md_type
; /* type of entry MDT_* */
592 u_int64_t md_data
; /* specific data */
593 u_int64_t md_cval
; /* common string label */
598 __elfN(parse_modmetadata
)(struct preloaded_file
*fp
, elf_file_t ef
)
600 struct mod_metadata md
;
601 #if defined(__i386__) && __ELF_WORD_SIZE == 64
602 struct mod_metadata64 md64
;
604 struct mod_depend
*mdepend
;
605 struct mod_version mver
;
608 int error
, modcnt
, minfolen
;
609 Elf_Addr v
, p
, p_stop
;
611 if (__elfN(lookup_symbol
)(fp
, ef
, "__start_set_modmetadata_set", &sym
) != 0)
613 p
= sym
.st_value
+ ef
->off
;
614 if (__elfN(lookup_symbol
)(fp
, ef
, "__stop_set_modmetadata_set", &sym
) != 0)
616 p_stop
= sym
.st_value
+ ef
->off
;
620 COPYOUT(p
, &v
, sizeof(v
));
621 error
= __elfN(reloc_ptr
)(fp
, ef
, p
, &v
, sizeof(v
));
622 if (error
== EOPNOTSUPP
)
626 #if defined(__i386__) && __ELF_WORD_SIZE == 64
627 COPYOUT(v
, &md64
, sizeof(md64
));
628 error
= __elfN(reloc_ptr
)(fp
, ef
, v
, &md64
, sizeof(md64
));
629 if (error
== EOPNOTSUPP
) {
630 md64
.md_cval
+= ef
->off
;
631 md64
.md_data
+= ef
->off
;
632 } else if (error
!= 0)
634 md
.md_version
= md64
.md_version
;
635 md
.md_type
= md64
.md_type
;
636 md
.md_cval
= (const char *)(uintptr_t)md64
.md_cval
;
637 md
.md_data
= (void *)(uintptr_t)md64
.md_data
;
639 COPYOUT(v
, &md
, sizeof(md
));
640 error
= __elfN(reloc_ptr
)(fp
, ef
, v
, &md
, sizeof(md
));
641 if (error
== EOPNOTSUPP
) {
642 md
.md_cval
+= ef
->off
;
643 md
.md_data
+= ef
->off
;
644 } else if (error
!= 0)
647 p
+= sizeof(Elf_Addr
);
650 if (ef
->kernel
) /* kernel must not depend on anything */
652 s
= strdupout((vm_offset_t
)md
.md_cval
);
653 minfolen
= sizeof(*mdepend
) + strlen(s
) + 1;
654 mdepend
= malloc(minfolen
);
657 COPYOUT((vm_offset_t
)md
.md_data
, mdepend
, sizeof(*mdepend
));
658 strcpy((char*)(mdepend
+ 1), s
);
660 file_addmetadata(fp
, MODINFOMD_DEPLIST
, minfolen
, mdepend
);
664 s
= strdupout((vm_offset_t
)md
.md_cval
);
665 COPYOUT((vm_offset_t
)md
.md_data
, &mver
, sizeof(mver
));
666 file_addmodule(fp
, s
, mver
.mv_version
, NULL
);
673 s
= fake_modname(fp
->f_name
);
674 file_addmodule(fp
, s
, 1, NULL
);
681 elf_hash(const char *name
)
683 const unsigned char *p
= (const unsigned char *) name
;
689 if ((g
= h
& 0xf0000000) != 0)
696 static const char __elfN(bad_symtable
)[] = "elf" __XSTRING(__ELF_WORD_SIZE
) "_lookup_symbol: corrupt symbol table\n";
698 __elfN(lookup_symbol
)(struct preloaded_file
*fp
, elf_file_t ef
, const char* name
,
706 hash
= elf_hash(name
);
707 COPYOUT(&ef
->buckets
[hash
% ef
->nbuckets
], &symnum
, sizeof(symnum
));
709 while (symnum
!= STN_UNDEF
) {
710 if (symnum
>= ef
->nchains
) {
711 printf(__elfN(bad_symtable
));
715 COPYOUT(ef
->symtab
+ symnum
, &sym
, sizeof(sym
));
716 if (sym
.st_name
== 0) {
717 printf(__elfN(bad_symtable
));
721 strp
= strdupout((vm_offset_t
)(ef
->strtab
+ sym
.st_name
));
722 if (strcmp(name
, strp
) == 0) {
724 if (sym
.st_shndx
!= SHN_UNDEF
||
725 (sym
.st_value
!= 0 &&
726 ELF_ST_TYPE(sym
.st_info
) == STT_FUNC
)) {
733 COPYOUT(&ef
->chains
[symnum
], &symnum
, sizeof(symnum
));
739 * Apply any intra-module relocations to the value. p is the load address
740 * of the value and val/len is the value to be modified. This does NOT modify
741 * the image in-place, because this is done by kern_linker later on.
743 * Returns EOPNOTSUPP if no relocation method is supplied.
746 __elfN(reloc_ptr
)(struct preloaded_file
*mp
, elf_file_t ef
,
747 Elf_Addr p
, void *val
, size_t len
)
755 * The kernel is already relocated, but we still want to apply
756 * offset adjustments.
761 for (n
= 0; n
< ef
->relsz
/ sizeof(r
); n
++) {
762 COPYOUT(ef
->rel
+ n
, &r
, sizeof(r
));
764 error
= __elfN(reloc
)(ef
, __elfN(symaddr
), &r
, ELF_RELOC_REL
,
765 ef
->off
, p
, val
, len
);
769 for (n
= 0; n
< ef
->relasz
/ sizeof(a
); n
++) {
770 COPYOUT(ef
->rela
+ n
, &a
, sizeof(a
));
772 error
= __elfN(reloc
)(ef
, __elfN(symaddr
), &a
, ELF_RELOC_RELA
,
773 ef
->off
, p
, val
, len
);
782 __elfN(symaddr
)(struct elf_file
*ef
, Elf_Size symidx
)
785 /* Symbol lookup by index not required here. */