From 16807ff976a8cf71babf9d28bcfe3ceb7911f142 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Mon, 23 Jun 2025 15:08:38 -0400 Subject: usr.bin: Add 'elfdump' tool Introduce the 'elfdump' utility to dump information relating to ELF files. This is useful for debugging purposes. Signed-off-by: Ian Moffett --- usr.bin/elfdump/Makefile | 6 ++ usr.bin/elfdump/elfdump.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 usr.bin/elfdump/Makefile create mode 100644 usr.bin/elfdump/elfdump.c (limited to 'usr.bin/elfdump') diff --git a/usr.bin/elfdump/Makefile b/usr.bin/elfdump/Makefile new file mode 100644 index 0000000..b450635 --- /dev/null +++ b/usr.bin/elfdump/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/elfdump: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/elfdump/elfdump.c b/usr.bin/elfdump/elfdump.c new file mode 100644 index 0000000..12394ba --- /dev/null +++ b/usr.bin/elfdump/elfdump.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +/* Ehdr.e_type table */ +static const char *elftype[] = { + [ET_NONE] = "Untyped", + [ET_REL] = "Relocatable", + [ET_EXEC] = "Executable", + [ET_DYN] = "Shared object", + [ET_CORE] "Core dump" +}; + +/* Phdr.p_type table */ +static const char *phdrtype[] = { + [PT_NULL] = "Null", + [PT_LOAD] = "Loadable", + [PT_DYNAMIC] = "Dynamic", + [PT_NOTE] = "Note (linker garbage)", +}; + +/* + * Verify the validity of the ELF header from its + * various fields such as magic bytes, ABI, endianness, + * etc. + * + * Returns 0 on success. + */ +static int +elf64_verify(const Elf64_Ehdr *hdr) +{ + const char *mag = &hdr->e_ident[EI_MAG0]; + + if (memcmp(mag, ELFMAG, SELFMAG) != 0) { + printf("Bad ELF magic\n"); + return -ENOEXEC; + } + if (hdr->e_ident[EI_OSABI] != ELFOSABI_SYSV) { + printf("Bad ELF ABI\n"); + return -ENOEXEC; + } + if (hdr->e_ident[EI_DATA] != ELFDATA2LSB) { + printf("Bad endianness\n"); + return -ENOEXEC; + } + if (hdr->e_ident[EI_CLASS] != ELFCLASS64) { + printf("ELF not 64 bits\n"); + return -ENOEXEC; + } + + return 0; +} + +static void +parse_phdrs(const Elf64_Ehdr *eh, int fd) +{ + Elf64_Phdr phdr; + const char *type = "Unknown"; + + lseek(fd, SEEK_SET, eh->e_phoff); + printf("-- PHDRS BEGIN --\n"); + for (size_t i = 0; i < eh->e_phnum; ++i) { + if (read(fd, &phdr, eh->e_phentsize) <= 0) { + printf("failed to read phdr %d\n", i); + break; + } + if (phdr.p_type < NELEM(phdrtype)) { + type = phdrtype[phdr.p_type]; + } + + printf("* [P.%d] Type: %s\n", i, type); + printf("* [P.%d] Offset: %d\n", i, phdr.p_offset); + printf("* [P.%d] Vaddr: %p\n", i, phdr.p_vaddr); + printf("* [P.%d] Paddr: %p\n", i, phdr.p_paddr); + printf("* [P.%d] Memory size: %d\n", i, phdr.p_memsz); + printf("* [P.%d] Flags: %p\n", i, phdr.p_flags); + printf("* [P.%d] Alignment: %p\n", i, phdr.p_align); + + /* Seperator */ + if (i < (eh->e_phnum - 1)) { + printf("-----------------------------\n"); + } + } + printf("-- PHDRS END --\n"); +} + +static int +parse_ehdr(const Elf64_Ehdr *eh, int fd) +{ + const char *elf_type = "Bad"; + + if (eh->e_type < NELEM(elftype)) { + elf_type = elftype[eh->e_type]; + } + + printf("* Entrypoint: %p\n", eh->e_entry); + printf("* Program headers start offset: %p\n", eh->e_phoff); + printf("* Section headers start offset: %p\n", eh->e_shoff); + printf("* Number of program headers: %d\n", eh->e_phnum); + printf("* Endianess: Little\n"); + parse_phdrs(eh, fd); + return 0; +} + +static int +elfdump_run(const char *filename) +{ + Elf64_Ehdr eh; + int fd, error; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + return fd; + } + + printf("-- Dumping %s --\n", filename); + read(fd, &eh, sizeof(eh)); + + if ((error = elf64_verify(&eh)) < 0) { + return error; + } + if ((error = parse_ehdr(&eh, fd)) < 0) { + return error; + } + + close(fd); + return 0; +} + +int +main(int argc, char **argv) +{ + if (argc < 2) { + printf("elfdump: usage: elfdump \n"); + return -1; + } + + return elfdump_run(argv[1]); +} -- cgit v1.2.3