1 /* $NetBSD: loadfile_elf32.c,v 1.30 2013/11/27 17:33:03 jakllsch Exp $ */
4 * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center and by Christos Zoulas.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 /* If not included by exec_elf64.c, ELFSIZE won't be defined. */
39 #include <lib/libsa/stand.h>
40 #include <lib/libkern/libkern.h>
51 #include <sys/param.h>
56 #if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \
57 ((ELFSIZE == 64) && defined(BOOT_ELF64))
59 #define ELFROUND (ELFSIZE / 8)
62 #include "byteorder.h"
65 * Byte swapping may be necessary in the non-_STANDLONE case because
66 * we may be built with a host compiler.
69 f = (bo == ELFDATA2LSB) ? sa_htole16(f) : sa_htobe16(f)
71 f = (bo == ELFDATA2LSB) ? sa_htole32(f) : sa_htobe32(f)
73 f = (bo == ELFDATA2LSB) ? sa_htole64(f) : sa_htobe64(f)
76 f = (bo == ELFDATA2LSB) ? sa_le16toh(f) : sa_be16toh(f)
78 f = (bo == ELFDATA2LSB) ? sa_le32toh(f) : sa_be32toh(f)
80 f = (bo == ELFDATA2LSB) ? sa_le64toh(f) : sa_be64toh(f)
83 internalize_ehdr(Elf_Byte bo
, Elf_Ehdr
*ehdr
)
95 I16(ehdr
->e_phentsize
);
97 I16(ehdr
->e_shentsize
);
99 I16(ehdr
->e_shstrndx
);
102 I16(ehdr
->e_machine
);
103 I32(ehdr
->e_version
);
109 I16(ehdr
->e_phentsize
);
111 I16(ehdr
->e_shentsize
);
113 I16(ehdr
->e_shstrndx
);
115 #error ELFSIZE is not 32 or 64
120 externalize_ehdr(Elf_Byte bo
, Elf_Ehdr
*ehdr
)
125 E16(ehdr
->e_machine
);
126 E32(ehdr
->e_version
);
132 E16(ehdr
->e_phentsize
);
134 E16(ehdr
->e_shentsize
);
136 E16(ehdr
->e_shstrndx
);
139 E16(ehdr
->e_machine
);
140 E32(ehdr
->e_version
);
146 E16(ehdr
->e_phentsize
);
148 E16(ehdr
->e_shentsize
);
150 E16(ehdr
->e_shstrndx
);
152 #error ELFSIZE is not 32 or 64
157 internalize_phdr(Elf_Byte bo
, Elf_Phdr
*phdr
)
179 #error ELFSIZE is not 32 or 64
184 internalize_shdr(Elf_Byte bo
, Elf_Shdr
*shdr
)
192 I32(shdr
->sh_offset
);
196 I32(shdr
->sh_addralign
);
197 I32(shdr
->sh_entsize
);
203 I64(shdr
->sh_offset
);
207 I64(shdr
->sh_addralign
);
208 I64(shdr
->sh_entsize
);
210 #error ELFSIZE is not 32 or 64
215 externalize_shdr(Elf_Byte bo
, Elf_Shdr
*shdr
)
223 E32(shdr
->sh_offset
);
227 E32(shdr
->sh_addralign
);
228 E32(shdr
->sh_entsize
);
234 E64(shdr
->sh_offset
);
238 E64(shdr
->sh_addralign
);
239 E64(shdr
->sh_entsize
);
241 #error ELFSIZE is not 32 or 64
244 #else /* _STANDALONE */
246 * Byte swapping is never necessary in the _STANDALONE case because
247 * we are being built with the target compiler.
249 #define internalize_ehdr(bo, ehdr) /* nothing */
250 #define externalize_ehdr(bo, ehdr) /* nothing */
252 #define internalize_phdr(bo, phdr) /* nothing */
254 #define internalize_shdr(bo, shdr) /* nothing */
255 #define externalize_shdr(bo, shdr) /* nothing */
256 #endif /* _STANDALONE */
259 ELFNAMEEND(loadfile
)(int fd
, Elf_Ehdr
*elf
, u_long
*marks
, int flags
)
267 Elf_Addr minp
= ~0, maxp
= 0, pos
= 0, elfp
= 0;
268 u_long offset
= marks
[MARK_START
];
272 uint8_t name
[ELF_NOTE_NETBSD_NAMESZ
+ 1];
273 uint8_t desc
[ELF_NOTE_NETBSD_DESCSZ
];
277 int boot_load_ctf
= 1;
279 /* some ports dont use the offset */
282 internalize_ehdr(elf
->e_ident
[EI_DATA
], elf
);
284 sz
= elf
->e_phnum
* sizeof(Elf_Phdr
);
287 if (lseek(fd
, elf
->e_phoff
, SEEK_SET
) == -1) {
288 WARN(("lseek phdr"));
291 nr
= read(fd
, phdr
, sz
);
293 WARN(("read program headers"));
298 WARN(("read program headers"));
302 for (first
= 1, i
= 0; i
< elf
->e_phnum
; i
++) {
303 internalize_phdr(elf
->e_ident
[EI_DATA
], &phdr
[i
]);
305 #ifndef MD_LOADSEG /* Allow processor ABI specific segment loads */
306 #define MD_LOADSEG(a) /*CONSTCOND*/0
308 if (MD_LOADSEG(&phdr
[i
]))
311 if (phdr
[i
].p_type
!= PT_LOAD
||
312 (phdr
[i
].p_flags
& (PF_W
|PF_X
)) == 0)
315 #define IS_TEXT(p) (p.p_flags & PF_X)
316 #define IS_DATA(p) (p.p_flags & PF_W)
317 #define IS_BSS(p) (p.p_filesz < p.p_memsz)
319 * XXX: Assume first address is lowest
321 if ((IS_TEXT(phdr
[i
]) && (flags
& LOAD_TEXT
)) ||
322 (IS_DATA(phdr
[i
]) && (flags
& LOAD_DATA
))) {
325 if (marks
[MARK_DATA
] == 0 && IS_DATA(phdr
[i
]))
326 marks
[MARK_DATA
] = LOADADDR(phdr
[i
].p_vaddr
);
328 /* Read in segment. */
329 PROGRESS(("%s%lu", first
? "" : "+",
330 (u_long
)phdr
[i
].p_filesz
));
332 if (lseek(fd
, phdr
[i
].p_offset
, SEEK_SET
) == -1) {
333 WARN(("lseek text"));
336 nr
= READ(fd
, phdr
[i
].p_vaddr
, phdr
[i
].p_filesz
);
338 WARN(("read text error"));
341 if (nr
!= (ssize_t
)phdr
[i
].p_filesz
) {
349 if ((IS_TEXT(phdr
[i
]) && (flags
& (LOAD_TEXT
|COUNT_TEXT
))) ||
350 (IS_DATA(phdr
[i
]) && (flags
& (LOAD_DATA
|COUNT_TEXT
)))) {
351 pos
= phdr
[i
].p_vaddr
;
354 pos
+= phdr
[i
].p_filesz
;
360 if (IS_BSS(phdr
[i
]) && (flags
& LOAD_BSS
)) {
362 (u_long
)(phdr
[i
].p_memsz
- phdr
[i
].p_filesz
)));
363 BZERO((phdr
[i
].p_vaddr
+ phdr
[i
].p_filesz
),
364 phdr
[i
].p_memsz
- phdr
[i
].p_filesz
);
366 if (IS_BSS(phdr
[i
]) && (flags
& (LOAD_BSS
|COUNT_BSS
))) {
367 pos
+= phdr
[i
].p_memsz
- phdr
[i
].p_filesz
;
375 * Copy the ELF and section headers.
377 maxp
= roundup(maxp
, ELFROUND
);
378 if (flags
& (LOAD_HDR
|COUNT_HDR
)) {
380 maxp
+= sizeof(Elf_Ehdr
);
383 if (flags
& (LOAD_SYM
|COUNT_SYM
)) {
384 if (lseek(fd
, elf
->e_shoff
, SEEK_SET
) == -1) {
385 WARN(("lseek section headers"));
388 sz
= elf
->e_shnum
* sizeof(Elf_Shdr
);
392 nr
= read(fd
, shp
, sz
);
394 WARN(("read section headers"));
399 WARN(("read section headers"));
404 maxp
+= roundup(sz
, ELFROUND
);
407 /* Internalize the section headers. */
408 for (i
= 0; i
< elf
->e_shnum
; i
++)
409 internalize_shdr(elf
->e_ident
[EI_DATA
], &shp
[i
]);
410 #endif /* ! _STANDALONE */
413 * First load the section names section.
415 if (boot_load_ctf
&& (elf
->e_shstrndx
!= 0)) {
416 if (flags
& LOAD_SYM
) {
417 if (lseek(fd
, shp
[elf
->e_shstrndx
].sh_offset
,
419 WARN(("lseek symbols"));
423 shp
[elf
->e_shstrndx
].sh_size
);
425 WARN(("read symbols"));
429 (ssize_t
)shp
[elf
->e_shstrndx
].sh_size
) {
431 WARN(("read symbols"));
435 shstr
= ALLOC(shp
[elf
->e_shstrndx
].sh_size
);
436 shstrsz
= shp
[elf
->e_shstrndx
].sh_size
;
437 if (lseek(fd
, shp
[elf
->e_shstrndx
].sh_offset
,
439 WARN(("lseek symbols"));
443 shp
[elf
->e_shstrndx
].sh_size
);
445 WARN(("read symbols"));
449 shp
[elf
->e_shstrndx
].sh_offset
= maxp
- elfp
;
450 maxp
+= roundup(shp
[elf
->e_shstrndx
].sh_size
, ELFROUND
);
454 * Now load the symbol sections themselves. Make sure
455 * the sections are aligned. Don't bother with any
456 * string table that isn't referenced by a symbol
459 for (first
= 1, i
= 0; i
< elf
->e_shnum
; i
++) {
460 if (i
== elf
->e_shstrndx
) {
461 /* already loaded this section */
464 switch (shp
[i
].sh_type
) {
466 if (boot_load_ctf
&& shstr
) {
467 /* got a CTF section? */
468 if (strncmp(".SUNW_ctf",
469 &shstr
[shp
[i
].sh_name
],
475 /* Not loading this, so zero out the offset. */
476 shp
[i
].sh_offset
= 0;
479 for (j
= 0; j
< elf
->e_shnum
; j
++)
480 if (shp
[j
].sh_type
== SHT_SYMTAB
&&
481 shp
[j
].sh_link
== (unsigned int)i
)
485 /* Not loading this, so zero out the offset. */
486 shp
[i
].sh_offset
= 0;
490 if (flags
& LOAD_SYM
) {
491 PROGRESS(("%s%ld", first
? " [" : "+",
492 (u_long
)shp
[i
].sh_size
));
493 if (lseek(fd
, shp
[i
].sh_offset
,
495 WARN(("lseek symbols"));
498 nr
= READ(fd
, maxp
, shp
[i
].sh_size
);
500 WARN(("read symbols"));
503 if (nr
!= (ssize_t
)shp
[i
].sh_size
) {
505 WARN(("read symbols"));
509 shp
[i
].sh_offset
= maxp
- elfp
;
510 maxp
+= roundup(shp
[i
].sh_size
, ELFROUND
);
514 if ((flags
& LOAD_NOTE
) == 0)
516 if (shp
[i
].sh_size
< sizeof(note
)) {
517 shp
[i
].sh_offset
= 0;
520 if (lseek(fd
, shp
[i
].sh_offset
, SEEK_SET
)
522 WARN(("lseek note"));
525 nr
= read(fd
, ¬e
, sizeof(note
));
530 if (note
.nh
.n_namesz
==
531 ELF_NOTE_NETBSD_NAMESZ
&&
533 ELF_NOTE_NETBSD_DESCSZ
&&
535 ELF_NOTE_TYPE_NETBSD_TAG
&&
536 memcmp(note
.name
, ELF_NOTE_NETBSD_NAME
,
537 sizeof(note
.name
)) == 0) {
538 memcpy(&netbsd_version
, ¬e
.desc
,
539 sizeof(netbsd_version
));
541 shp
[i
].sh_offset
= 0;
545 if (flags
& LOAD_SYM
) {
547 /* Externalize the section headers. */
548 for (i
= 0; i
< elf
->e_shnum
; i
++)
549 externalize_shdr(elf
->e_ident
[EI_DATA
],
551 #endif /* ! _STANDALONE */
552 BCOPY(shp
, shpp
, sz
);
561 DEALLOC(shstr
, shstrsz
);
565 * Frob the copied ELF header to give information relative
568 if (flags
& LOAD_HDR
) {
570 elf
->e_shoff
= sizeof(Elf_Ehdr
);
571 elf
->e_phentsize
= 0;
573 externalize_ehdr(elf
->e_ident
[EI_DATA
], elf
);
574 BCOPY(elf
, elfp
, sizeof(*elf
));
575 internalize_ehdr(elf
->e_ident
[EI_DATA
], elf
);
578 marks
[MARK_START
] = LOADADDR(minp
);
579 marks
[MARK_ENTRY
] = LOADADDR(elf
->e_entry
);
581 * Since there can be more than one symbol section in the code
582 * and we need to find strtab too in order to do anything
583 * useful with the symbols, we just pass the whole elf
584 * header back and we let the kernel debugger find the
585 * location and number of symbols by itself.
587 marks
[MARK_NSYM
] = 1; /* XXX: Kernel needs >= 0 */
588 marks
[MARK_SYM
] = LOADADDR(elfp
);
589 marks
[MARK_END
] = LOADADDR(maxp
);
604 u_int32_t netbsd_version
;
606 main(int argc
, char *argv
[])
609 u_long marks
[MARK_MAX
];
612 (void)fprintf(stderr
, "Usage: %s <file>\n", getprogname());
615 if ((fd
= open(argv
[1], O_RDONLY
)) == -1)
616 err(1, "Can't open `%s'", argv
[1]);
617 if (read(fd
, &elf
, sizeof(elf
)) != sizeof(elf
))
618 err(1, "Can't read `%s'", argv
[1]);
619 memset(marks
, 0, sizeof(marks
));
620 marks
[MARK_START
] = (u_long
)malloc(2LL * 1024 * 2024 * 1024);
621 ELFNAMEEND(loadfile
)(fd
, &elf
, marks
, LOAD_ALL
);
622 printf("%d\n", netbsd_version
);
627 #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */