From 253bcee5d050ca2e0ba3c884c722edfb89ed03ce Mon Sep 17 00:00:00 2001 From: Armin Luntzer <armin.luntzer@univie.ac.at> Date: Tue, 14 Mar 2017 13:44:43 +0100 Subject: [PATCH] * import Xentium kernel loader * split ELF stuff from modules * add swab.h * add more generic string functions --- arch/sparc/kernel/irq.c | 1 + include/asm-generic/swab.h | 45 ++ include/elf.h | 567 +++++++++++++++++++++++++ include/kernel/elf.h | 42 ++ include/kernel/module.h | 13 +- include/kernel/string.h | 5 + include/kernel/xentium.h | 35 ++ init/main.c | 13 + kernel/Makefile | 1 + kernel/module.c | 678 ++++-------------------------- kernel/xentium.c | 304 ++++++++++++++ lib/Makefile | 1 + lib/elf.c | 831 +++++++++++++++++++++++++++++++++++++ lib/string.c | 51 +++ 14 files changed, 1972 insertions(+), 615 deletions(-) create mode 100644 include/asm-generic/swab.h create mode 100644 include/elf.h create mode 100644 include/kernel/xentium.h create mode 100644 kernel/xentium.c create mode 100644 lib/elf.c diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index 8a2aadb..a372b8a 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -44,6 +44,7 @@ #include <kernel/irq.h> #include <kernel/kmem.h> #include <kernel/printk.h> +#include <kernel/kernel.h> #include <errno.h> #include <list.h> diff --git a/include/asm-generic/swab.h b/include/asm-generic/swab.h new file mode 100644 index 0000000..2d0f816 --- /dev/null +++ b/include/asm-generic/swab.h @@ -0,0 +1,45 @@ +/** + * @file include/asm-generic/swab.h + * + * @copyright GPLv2 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _ASM_GENERIC_SWAB_H_ +#define _ASM_GENERIC_SWAB_H_ + +#include <kernel/types.h> + +#define swab16(x) ((uint16_t)( \ + (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \ + (((uint16_t)(x) & (uint16_t)0xff00U) >> 8))) + +#define swab32(x) ((uint32_t)( \ + (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24))) + + +#define swahw32(x) ((uint32_t)( \ + (((uint32_t)(x) & (uint32_t)0x0000ffffUL) << 16) | \ + (((uint32_t)(x) & (uint32_t)0xffff0000UL) >> 16))) + +#define swahb32(x) ((uint32_t)( \ + (((uint32_t)(x) & (uint32_t)0x00ff00ffUL) << 8) | \ + (((uint32_t)(x) & (uint32_t)0xff00ff00UL) >> 8))) + +#define swabb32(x) ((uint32_t)( \ + (((uint32_t)(x) & (uint32_t)0x0f0f0f0fUL) << 4) | \ + (((uint32_t)(x) & (uint32_t)0xf0f0f0f0UL) >> 4))) + +#endif /* _ASM_GENERIC_SWAB_H_ */ diff --git a/include/elf.h b/include/elf.h new file mode 100644 index 0000000..883eeae --- /dev/null +++ b/include/elf.h @@ -0,0 +1,567 @@ +#ifndef _KERNEL_ELF_H_ +#define _KERNEL_ELF_H_ + + +#include <kernel/types.h> + +/* some ELF constants&stuff ripped from include/uapi/linux/elf.h */ + + +/* 32-bit base types */ +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* 64-bit base types */ +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + + +__extension__ +typedef struct elf32_dyn { + Elf32_Sword d_tag; /* dynamic array tag */ + union{ + Elf32_Sword d_val; + Elf32_Addr d_ptr; /* program virtual address */ + }; +} Elf32_Dyn; + +__extension__ +typedef struct elf64_dyn { + Elf64_Sxword d_tag; /* entry tag value */ + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + }; +} Elf64_Dyn; + +/* The following are used with relocations */ +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +#define ELF64_R_SYM(x) ((x) >> 32) +#define ELF64_R_TYPE(x) ((x) & 0xffffffff) + +/* Dynamic Array Tags */ +#define DT_NULL 0 /* end of _DYNAMIC array */ +#define DT_NEEDED 1 /* str tbl offset of needed librart */ +#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */ +#define DT_PLTGOT 3 /* address PLT/GOT */ +#define DT_HASH 4 /* address of symbol hash table */ +#define DT_STRTAB 5 /* address of string table */ +#define DT_SYMTAB 6 /* address of symbol table */ +#define DT_RELA 7 /* address of relocation table */ +#define DT_RELASZ 8 /* size of relocation table */ +#define DT_RELAENT 9 /* size of relocation entry */ +#define DT_STRSZ 10 /* size of string table */ +#define DT_SYMENT 11 /* size of symbol table entry */ +#define DT_INIT 12 /* address of initialization func. */ +#define DT_FINI 13 /* address of termination function */ +#define DT_SONAME 14 /* string tbl offset of shared obj */ +#define DT_RPATH 15 /* str tbl offset of lib search path */ +#define DT_SYMBOLIC 16 /* start symbol search in shared obj */ +#define DT_REL 17 /* address of reloc tbl with addends */ +#define DT_RELSZ 18 /* size of DT_REL relocation table */ +#define DT_RELENT 19 /* size of DT_REL relocation entry */ +#define DT_PLTREL 20 /* PLT referenced relocation entry */ +#define DT_DEBUG 21 /* used for debugging */ +#define DT_TEXTREL 22 /* allow reloc mod to unwritable seg */ +#define DT_JMPREL 23 /* addr of PLT's relocation entries */ +#define DT_ENCODING 32 +#define OLD_DT_LOOS 0x60000000 +#define DT_LOOS 0x6000000d +#define DT_HIOS 0x6ffff000 +#define DT_VALRNGLO 0x6ffffd00 +#define DT_VALRNGHI 0x6ffffdff +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_VERSYM 0x6ffffff0 +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff +#define OLD_DT_HIOS 0x6fffffff +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + + +/* Dynamic Flags - DT_FLAGS_1 .dynamic entry */ +#define DF_1_NOW 0x00000001 +#define DF_1_GLOBAL 0x00000002 +#define DF_1_GROUP 0x00000004 +#define DF_1_NODELETE 0x00000008 +#define DF_1_LOADFLTR 0x00000010 +#define DF_1_INITFIRST 0x00000020 +#define DF_1_NOOPEN 0x00000040 +#define DF_1_ORIGIN 0x00000080 +#define DF_1_DIRECT 0x00000100 +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 +#define DF_1_NODEFLIB 0x00000800 +#define DF_1_NODUMP 0x00001000 +#define DF_1_CONLFAT 0x00002000 + +/* ld.so: number of low tags that are used saved internally (0 .. DT_NUM-1) */ +#define DT_NUM (DT_JMPREL+1) + +/* This info is needed when parsing the symbol table */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) + + + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel { + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_rela{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf64_rela { + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ + Elf64_Sxword r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + + +/* relocs as needed */ +#define R_AMD64_NONE 0 +#define R_AMD64_RELATIVE 8 + + + + +typedef struct elf32_sym{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym { + Elf64_Word st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf64_Half st_shndx; /* Associated section index */ + Elf64_Addr st_value; /* Value of the symbol */ + Elf64_Xword st_size; /* Associated symbol size */ +} Elf64_Sym; + + + + + + + + + + + + + + +/* + * Note Definitions + */ +typedef struct { + Elf32_Word namesz; + Elf32_Word descsz; + Elf32_Word type; +} Elf32_Note; + +typedef struct { + Elf64_Half namesz; + Elf64_Half descsz; + Elf64_Half type; +} Elf64_Note; + + + + + +/** + * e_ident[] identification indexes + */ + +#define EI_MAG0 0 /* file ID */ +#define EI_MAG1 1 /* file ID */ +#define EI_MAG2 2 /* file ID */ +#define EI_MAG3 3 /* file ID */ +#define EI_CLASS 4 /* file class */ +#define EI_DATA 5 /* data encoding */ +#define EI_VERSION 6 /* ELF header version */ +#define EI_OSABI 7 /* OS/ABI ID */ +#define EI_ABIVERSION 8 /* ABI version */ +#define EI_PAD 9 /* start of pad bytes */ +#define EI_NIDENT 16 /* size of e_ident[] */ + +/* e_ident[] magic numbers */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ +#define ELFMAG "\177ELF" /* magic */ +#define SELFMAG 4 /* size of magic */ + +/* e_ident[] file classes */ +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASS32 1 /* 32-bit objs */ +#define ELFCLASS64 2 /* 64-bit objs */ +#define ELFCLASSNUM 3 /* number of classes */ + +/* e_ident[] data encoding */ +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* Little-Endian */ +#define ELFDATA2MSB 2 /* Big-Endian */ +#define ELFDATANUM 3 /* number of data encode defines */ + +/* e_ident[] Operating System/ABI */ +#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_MONTEREY 7 /* Monterey */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + + +/* e_version */ +#define EV_NONE 0 +#define EV_CURRENT 1 +#define EV_NUM 2 /* number of versions */ + +/* e_type */ +#define ET_NONE 0 +#define ET_REL 1 /* relocatable */ +#define ET_EXEC 2 /* executable */ +#define ET_DYN 3 /* shared object*/ +#define ET_CORE 4 /* core file */ +#define ET_NUM 5 /* number of types */ +#define ET_LOPROC 0xff00 /* reserved range for processor */ +#define ET_HIPROC 0xffff /* specific e_type */ + +/* e_machine */ +#define EM_NONE 0 +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_486 6 /* Intel 80486 - unused? */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_SPARC64 11 /* SPARC v9 64-bit unofficial */ +#define EM_PARISC 15 /* HPPA */ +#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ +#define EM_PPC 20 /* PowerPC */ +#define EM_ARM 40 /* ARM AArch32 */ +#define EM_ALPHA 41 /* DEC ALPHA */ +#define EM_SH 42 /* Hitachi/Renesas Super-H */ +#define EM_SPARCV9 43 /* SPARC version 9 */ +#define EM_IA_64 50 /* Intel IA-64 Processor */ +#define EM_AMD64 62 /* AMD64 architecture */ +#define EM_VAX 75 /* DEC VAX */ +#define EM_AARCH64 183 /* ARM AArch64 */ + + +/* ELF32 Header */ +typedef struct elf32_hdr{ + unsigned char e_ident[EI_NIDENT]; /* ELF identifier */ + Elf32_Half e_type; /* object file type */ + Elf32_Half e_machine; /* machine type */ + Elf32_Word e_version; /* object file version */ + Elf32_Addr e_entry; /* entry point */ + Elf32_Off e_phoff; /* program header offset */ + Elf32_Off e_shoff; /* section header offset */ + Elf32_Word e_flags; /* processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size */ + Elf32_Half e_phentsize; /* program header entry size */ + Elf32_Half e_phnum; /* number of program headers */ + Elf32_Half e_shentsize; /* section header entry size */ + Elf32_Half e_shnum; /* number of section headers */ + Elf32_Half e_shstrndx; /* string table index */ +} Elf32_Ehdr; + +/* ELF64 Header */ +typedef struct elf64_hdr{ + unsigned char e_ident[EI_NIDENT]; /* ELF identifier */ + Elf64_Half e_type; /* object file type */ + Elf64_Half e_machine; /* machine type */ + Elf64_Word e_version; /* object file version */ + Elf64_Addr e_entry; /* entry point */ + Elf64_Off e_phoff; /* program header offset */ + Elf64_Off e_shoff; /* section header offset */ + Elf64_Word e_flags; /* processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size */ + Elf64_Half e_phentsize; /* program header entry size */ + Elf64_Half e_phnum; /* number of program headers */ + Elf64_Half e_shentsize; /* section header entry size */ + Elf64_Half e_shnum; /* number of section headers */ + Elf64_Half e_shstrndx; /* string table index */ +} Elf64_Ehdr; + + +/* ELF32 Program Header */ +typedef struct elf32_phdr{ + Elf32_Word p_type; /* entry type */ + Elf32_Off p_flags; /* flags */ + Elf32_Addr p_offset; /* file offset */ + Elf32_Addr p_vaddr; /* virtual address */ + Elf32_Word p_paddr; /* physical address */ + Elf32_Word p_filesz; /* size in file */ + Elf32_Word p_memsz; /* size in memory */ + Elf32_Word p_align; /* alignment, file & memory */ +} Elf32_Phdr; + +/* ELF64 Program Header */ +typedef struct elf64_phdr { + Elf64_Word p_type; /* entry type */ + Elf64_Word p_flags; /* flags */ + Elf64_Off p_offset; /* file offset */ + Elf64_Addr p_vaddr; /* virtual address */ + Elf64_Addr p_paddr; /* physical address */ + Elf64_Xword p_filesz; /* size in file */ + Elf64_Xword p_memsz; /* size in memory */ + Elf64_Xword p_align; /* alignment, file & memory */ +} Elf64_Phdr; + + +/* Program entry types */ +#define PT_NULL 0 /* unused */ +#define PT_LOAD 1 /* loadable segment */ +#define PT_DYNAMIC 2 /* dynamic linking section */ +#define PT_INTERP 3 /* the RTLD */ +#define PT_NOTE 4 /* auxiliary information */ +#define PT_SHLIB 5 /* reserved - purpose undefined */ +#define PT_PHDR 6 /* program header */ +#define PT_TLS 7 /* thread local storage */ +#define PT_LOOS 0x60000000 /* reserved range for OS */ +#define PT_HIOS 0x6fffffff /* specific segment types */ +#define PT_LOPROC 0x70000000 /* reserved range for processor */ +#define PT_HIPROC 0x7fffffff /* specific segment types */ + + +/* ELF32 Section Header */ +typedef struct elf32_shdr { + Elf32_Word sh_name; /* section name index */ + Elf32_Word sh_type; /* section type */ + Elf32_Word sh_flags; /* section flags */ + Elf32_Addr sh_addr; /* (virtual) address */ + Elf32_Off sh_offset; /* file offset */ + Elf32_Word sh_size; /* section size */ + Elf32_Word sh_link; /* link to other section header */ + Elf32_Word sh_info; /* misc info */ + Elf32_Word sh_addralign; /* memory address alignment */ + Elf32_Word sh_entsize; /* section entry size */ +} Elf32_Shdr; + +/* ELF64 Section Header */ +typedef struct elf64_shdr { + Elf64_Word sh_name; /* section name */ + Elf64_Word sh_type; /* section type */ + Elf64_Xword sh_flags; /* section flags */ + Elf64_Addr sh_addr; /* (virtual) address */ + Elf64_Off sh_offset; /* file offset */ + Elf64_Xword sh_size; /* section size */ + Elf64_Word sh_link; /* link to other section header */ + Elf64_Word sh_info; /* misc info */ + Elf64_Xword sh_addralign; /* memory address alignment */ + Elf64_Xword sh_entsize; /* section entry size */ +} Elf64_Shdr; + + +/* Special Section Indexes */ +#define SHN_UNDEF 0 /* undefined */ +#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */ +#define SHN_LOPROC 0xff00 /* reserved range for processor */ +#define SHN_HIPROC 0xff1f /* specific section indexes */ +#define SHN_ABS 0xfff1 /* absolute value */ +#define SHN_COMMON 0xfff2 /* common symbol */ +#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends*/ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relation section without addends */ +#define SHT_SHLIB 10 /* reserved */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_NUM 12 /* number of section types */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Section names */ +#define ELF_BSS ".bss" /* uninitialized data */ +#define ELF_DATA ".data" /* initialized data */ +#define ELF_DEBUG ".debug" /* debug */ +#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */ +#define ELF_DYNSTR ".dynstr" /* dynamic string table */ +#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */ +#define ELF_FINI ".fini" /* termination code */ +#define ELF_GOT ".got" /* global offset table */ +#define ELF_HASH ".hash" /* symbol hash table */ +#define ELF_INIT ".init" /* initialization code */ +#define ELF_REL_DATA ".rel.data" /* relocation data */ +#define ELF_REL_FINI ".rel.fini" /* relocation termination code */ +#define ELF_REL_INIT ".rel.init" /* relocation initialization code */ +#define ELF_REL_DYN ".rel.dyn" /* relocation dynamic link info */ +#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */ +#define ELF_REL_TEXT ".rel.text" /* relocation code */ +#define ELF_RODATA ".rodata" /* read-only data */ +#define ELF_SHSTRTAB ".shstrtab" /* section header string table */ +#define ELF_STRTAB ".strtab" /* string table */ +#define ELF_SYMTAB ".symtab" /* symbol table */ +#define ELF_TEXT ".text" /* code */ + + +/* Section Attribute Flags - sh_flags */ +#define SHF_WRITE 0x1 /* Writable */ +#define SHF_ALLOC 0x2 /* occupies memory */ +#define SHF_EXECINSTR 0x4 /* executable */ +#define SHF_TLS 0x400 /* thread local storage */ +#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor + * specific section attributes */ + + +/* Sparc ELF relocation types */ +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 + + + + +/* end of ELF stuff */ + + + +/* begin configurable section */ + +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Phdr Elf_Phdr; +typedef Elf32_Dyn Elf_Dyn; +typedef Elf32_Rel Elf_Rel; +typedef Elf32_Rela Elf_Rela; +typedef Elf32_Off Elf_Off; +typedef Elf32_Addr Elf_Addr; +typedef Elf32_Sym Elf_Sym; + +#define ELF_R_SYM(x) ELF32_R_SYM(x) +#define ELF_R_TYPE(x) ELF32_R_TYPE(x) + + + +/** + * NOTE: no free configuration, limited to 32bit ELF, SPARCv8, big endian, + * because I am lazy :) + */ +#if 1 +#define ELF_ENDIAN ELFDATA2MSB +#define EM_MACHINE EM_SPARC +#else +#define ELF_ENDIAN ELFDATA2LSB +#define EM_MACHINE EM_AMD64 +#endif + + +#define elf_check_arch(x) ((x)->e_machine == EM_MACHINE) +#define elf_check_endian(x) ((x)->e_ident[EI_DATA] == ELF_ENDIAN) + + +/* implemented in arch code */ +int elf_header_check(Elf_Ehdr *ehdr); + + +#endif /* _KERNEL_ELF_H_ */ diff --git a/include/kernel/elf.h b/include/kernel/elf.h index 883eeae..4797c13 100644 --- a/include/kernel/elf.h +++ b/include/kernel/elf.h @@ -564,4 +564,46 @@ typedef Elf32_Sym Elf_Sym; int elf_header_check(Elf_Ehdr *ehdr); + +Elf_Shdr *elf_get_shdr(const Elf_Ehdr *ehdr); +size_t elf_find_shdr_alloc_idx(const Elf_Ehdr *ehdr, const size_t offset); + +Elf_Shdr *elf_get_sec_by_idx(const Elf_Ehdr *ehdr, const size_t idx); +Elf_Shdr *elf_get_sec_shstrtab(const Elf_Ehdr *ehdr); +char *elf_get_shstrtab_str(const Elf_Ehdr *ehdr, size_t idx); + +Elf_Shdr *elf_find_sec(const Elf_Ehdr *ehdr, const char *name); + +char *elf_get_strtab(const Elf_Ehdr *ehdr); +char *elf_get_strtab_str(const Elf_Ehdr *ehdr, size_t idx); + +char *elf_get_dynstr(const Elf_Ehdr *ehdr); +char *elf_get_dynstr_str(const Elf_Ehdr *ehdr, size_t idx); + +char *elf_get_symbol_str(const Elf_Ehdr *ehdr, size_t idx); + +unsigned long elf_get_symbol_value(const Elf_Ehdr *ehdr, + const char *name, unsigned long *value); + +unsigned long elf_get_symbol_type(const Elf_Ehdr *ehdr, const char *name); + +size_t elf_find_sec_idx_by_type(const Elf_Ehdr *ehdr, + const uint32_t sh_type, + const size_t offset); + +size_t elf_get_num_alloc_sections(const Elf_Ehdr *ehdr); + +size_t elf_get_num_dyn_entries(const Elf_Ehdr *ehdr); + +Elf_Dyn *elf_find_dyn(const Elf_Ehdr *ehdr, + const unsigned long d_tag, + const unsigned int offset); + +void elf_hdr_endianess_swap(Elf_Ehdr *ehdr); + +void elf_dump_strtab(const Elf_Ehdr *ehdr); +void elf_dump_symtab(const Elf_Ehdr *ehdr); +void elf_dump_sections(const Elf_Ehdr *ehdr); + + #endif /* _KERNEL_ELF_H_ */ diff --git a/include/kernel/module.h b/include/kernel/module.h index 281745f..f651c3d 100644 --- a/include/kernel/module.h +++ b/include/kernel/module.h @@ -36,17 +36,8 @@ struct elf_module { unsigned int align; Elf_Ehdr *ehdr; /* coincides with start of module image */ - Elf_Shdr *shdr; - Elf_Dyn *dyn; - + size_t size; - size_t dyn_size; - size_t sh_size; - size_t str_size; - - char *dyn_str; /* dynamic symbols string tab */ - char *sh_str; /* section header string tab */ - char *str; /* stringtab */ struct module_section *sec; size_t num_sec; @@ -58,11 +49,11 @@ struct elf_module { int apply_relocate_add(struct elf_module *m, Elf_Rela *rel, Elf_Addr sym); - struct module_section *find_mod_sec(const struct elf_module *m, const char *name); int module_load(struct elf_module *m, void *p); + void modules_list_loaded(void); #endif /* _KERNEL_MODULE_H_ */ diff --git a/include/kernel/string.h b/include/kernel/string.h index 37e7490..c006b78 100644 --- a/include/kernel/string.h +++ b/include/kernel/string.h @@ -5,6 +5,9 @@ #ifndef _KERNEL_STRING_H_ #define _KERNEL_STRING_H_ +#include <kernel/types.h> + + int sprintf(char *str, const char *format, ...); int strcmp(const char *s1, const char *s2); char *strpbrk(const char *s, const char *accept); @@ -12,6 +15,8 @@ char *strsep(char **stringp, const char *delim); size_t strlen(const char *s); void *memcpy(void *dest, const void *src, size_t n); +char *strcpy(char *dest, const char *src); +void bzero(void *s, size_t n); int isspace(int c); int atoi(const char *nptr); diff --git a/include/kernel/xentium.h b/include/kernel/xentium.h new file mode 100644 index 0000000..b28eee9 --- /dev/null +++ b/include/kernel/xentium.h @@ -0,0 +1,35 @@ +#ifndef _KERNEL_XENTIUM_H_ +#define _KERNEL_XENTIUM_H_ + +#include <kernel/init.h> +#include <kernel/elf.h> + +struct xen_module_section { + char *name; + unsigned long addr; + size_t size; +}; + +struct xen_kernel { + + unsigned long ep; + + + int refcnt; + + unsigned int align; + + Elf_Ehdr *ehdr; /* coincides with start of module image */ + + size_t size; + + + struct xen_module_section *sec; + size_t num_sec; +}; + + + +int xentium_kernel_load(struct xen_kernel *x, void *p); + +#endif /* _KERNEL_XENTIUM_H_ */ diff --git a/init/main.c b/init/main.c index d4914a3..5a31e98 100644 --- a/init/main.c +++ b/init/main.c @@ -16,6 +16,8 @@ #include <kernel/sbrk.h> #include <kernel/sysctl.h> +#include <kernel/xentium.h> + #define MSG "MAIN: " void module_image_load_embedded(void); @@ -38,6 +40,7 @@ int main(void) { void *addr; struct elf_module m; + struct xen_kernel x; kernel_init(); @@ -62,14 +65,24 @@ int main(void) /* addr = module_lookup_symbol_embedded("somefunction"); */ /* XXX the image is not necessary aligned properly, so we can't access * it directly, until we have a MNA trap */ +#if 1 + addr = module_read_embedded("testkernel.ko"); + + printk(MSG "testkernel module address is %p\n", addr); + if (addr) + xentium_kernel_load(&x, addr); +#endif +#if 0 addr = module_read_embedded("noc_dma.ko"); pr_debug(MSG "noc_dma module address is %p\n", addr); if (addr) module_load(&m, addr); + +#endif #if 0 modules_list_loaded(); #endif diff --git a/kernel/Makefile b/kernel/Makefile index b163e87..ff7d2e7 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -5,3 +5,4 @@ obj-y += bitmap.o obj-y += module.o obj-$(CONFIG_NOC_DMA) += noc_dma.o obj-y += irq.o +obj-y += xentium.o diff --git a/kernel/module.c b/kernel/module.c index bdab605..d205671 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -9,11 +9,8 @@ * 4. profit */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - #include <kernel/printk.h> +#include <kernel/string.h> #include <kernel/err.h> #include <kernel/module.h> #include <kernel/ksym.h> @@ -35,207 +32,12 @@ static struct { } _kmod; - /** - * @brief find section headers marked ALLOC by index - * - * @param offset a offset into the table (to locate multiple identical types) - * - * @return section index or 0 if not found - */ - -static unsigned int find_shdr_alloc(const struct elf_module *m, - const unsigned int offset) -{ - size_t i; - - - for (i = offset; i < m->ehdr->e_shnum; i++) { - if ((m->shdr[i].sh_flags & SHF_ALLOC)) - return i; - } - - return 0; -} - - - -/** - * @brief get number of sections marked ALLOC with size > 0 - * - * @return number of ALLOC sections - */ - -static unsigned int get_num_alloc_sections(const struct elf_module *m) -{ - size_t i; - size_t cnt = 0; - - - for (i = 0; i < m->ehdr->e_shnum; i++) { - if ((m->shdr[i].sh_flags & SHF_ALLOC)) - if (m->shdr[i].sh_size) - cnt++; - } - - return cnt; -} - - -/** - * @brief get the number of entries in a dynamic section - * - * @return the number of entries in a dynamic section - */ - -static unsigned int get_num_dyn_entries(const struct elf_module *m) -{ - return m->dyn_size / sizeof(Elf_Dyn); -} - - -/** - * @brief find a dynamic entry by tag - * - * @param offset a offset into the table (to locate multiple identical types) - * - * @return NULL if entry not found, pointer to entry otherwise - * - */ -__attribute__((unused)) -static Elf_Dyn *find_dyn(const struct elf_module *m, - const typeof(m->dyn->d_tag) d_tag, - const unsigned int offset) -{ - size_t i; - - - for (i = offset; i < get_num_dyn_entries(m); i++) - if (d_tag == m->dyn[i].d_tag) - return &m->dyn[i]; - - return NULL; -} - - -/** - * @brief return a section header by index - * - * @return NULL if entry not found, pointer to entry otherwise - * - */ - -static Elf_Shdr *get_sec(const struct elf_module *m, unsigned int idx) -{ - if (idx < m->ehdr->e_shnum) - return &m->shdr[idx]; - - return NULL; -} - - -/** - * @brief find find an elf section by type - * - * @param offset a offset into the table (to locate multiple identical types) - * - * @return section index or 0 if not found - * - */ - -static unsigned int find_sec_type(const struct elf_module *m, - const typeof(m->shdr->sh_type) sh_type, - const unsigned int offset) -{ - size_t i; - - - for (i = offset; i < m->ehdr->e_shnum; i++) { - if (sh_type == m->shdr[i].sh_type) - return i; - } - - return 0; -} - - -/** - * @brief find an elf section by name - * - * @return section index or 0 if not found - */ - -static unsigned int find_sec(const struct elf_module *m, const char *name) -{ - size_t i; - - - for (i = 1; i < m->ehdr->e_shnum; i++) { - if (!strcmp(m->sh_str + m->shdr[i].sh_name, name)) - return i; - } - - return 0; -} - - -/** - * @brief get an entry in the .shstrtab - * - * @return pointer to the start of the string or NULL if not found - */ - -static char *get_shstrtab_str(const struct elf_module *m, unsigned int idx) -{ - if (idx < m->sh_size) - return (m->sh_str + m->shdr[idx].sh_name); - - return NULL; -} - - -/** - * @brief get an entry in the .strtab + * @brief find module section by name * - * @return pointer to the start of the string or NULL if not found - */ - -__attribute__((unused)) -static char *get_strtab_str(const struct elf_module *m, unsigned int idx) -{ - if (idx < m->str_size) - return (m->str + idx); - - return NULL; -} - - -/** - * @brief get the name of a symbol in .symtab with a given index + * @param m a struct elf_module * - * @return pointer to the start of the string or NULL if not found - */ - -static char *get_symbol_str(const struct elf_module *m, unsigned int idx) -{ - Elf_Shdr *symtab; - Elf_Sym *symbols; - - - symtab = &m->shdr[find_sec(m, ".symtab")]; - - //symbols = (Elf_Sym *) (m->pa + symtab->sh_offset); - symbols = (Elf_Sym *) ((unsigned long) m->ehdr + symtab->sh_offset); - - if (idx < symtab->sh_size / symtab->sh_entsize) - return m->str + symbols[idx].st_name; - - return NULL; -} - - -/** - * @brief find module section by name + * @param name the name of the module section * * @return module section structure pointer or NULL if not found */ @@ -247,6 +49,9 @@ struct module_section *find_mod_sec(const struct elf_module *m, size_t i; + if (!name) + return NULL; + for (i = 0; i < m->num_sec; i++) { if (!strcmp(m->sec[i].name, name)) return &m->sec[i]; @@ -257,364 +62,11 @@ struct module_section *find_mod_sec(const struct elf_module *m, } -/** - * @brief dump the name of all elf sections - */ - -void dump_sections(const struct elf_module *m) -{ - size_t i; - - - printk(MOD "SECTIONS:\n" - MOD "============================\n" - MOD "\t[NUM]\t[NAME]\t\t\t[TYPE]\t\t[SIZE]\t[ENTSZ]\t[FLAGS]\n" - ); - - - for (i = 0; i < m->ehdr->e_shnum; i++) { - - printk(MOD "\t%d\t%-20s", i, m->sh_str + m->shdr[i].sh_name); - - switch (m->shdr[i].sh_type) { - case SHT_NULL: - printk("%-10s", "\tNULL"); break; - case SHT_PROGBITS: - printk("%-10s", "\tPROGBITS"); - break; - case SHT_SYMTAB: - printk("%-10s", "\tSYMTAB"); break; - case SHT_STRTAB: - printk("%-10s", "\tSTRTAB"); break; - case SHT_RELA : - printk("%-10s", "\tRELA"); break; - case SHT_HASH : - printk("%-10s", "\tHASH"); break; - case SHT_DYNAMIC: - printk("%-10s", "\tDYNAMIC"); break; - case SHT_NOTE : - printk("%-10s", "\tNOTE"); break; - case SHT_NOBITS: - printk("%-10s", "\tNOBITS"); break; - case SHT_REL : - printk("%-10s", "\tREL"); break; - case SHT_SHLIB : - printk("%-10s", "\tSHLIB"); break; - case SHT_DYNSYM: - printk("%-10s", "\tDYNSYM"); break; - case SHT_NUM : - printk("%-10s", "\tNUM"); break; - default: - printk("%-10s", "\tOTHER"); break; - } - - printk("\t%ld\t%ld\t", m->shdr[i].sh_size, m->shdr[i].sh_entsize); - - if (m->shdr[i].sh_flags & SHF_WRITE) - printk("WRITE "); - if (m->shdr[i].sh_flags & SHF_ALLOC) - printk("ALLOC "); - if (m->shdr[i].sh_flags & SHF_EXECINSTR) - printk("EXECINSTR "); - if (m->shdr[i].sh_flags & SHF_TLS) - printk("TLS "); - if (m->shdr[i].sh_flags & SHF_MASKPROC) - printk("MASKPROC "); - - printk(MOD "\n"); - - } - -} - - -/** - * @brief get the type of a symbol - * - * @return 1 if symbol has been found, 0 otherwise - */ - -static unsigned long get_symbol_type(const struct elf_module *m, - const char *name) - -{ - unsigned int i; - unsigned int idx; - size_t sym_cnt; - - Elf_Shdr *symtab; - Elf_Sym *symbols; - - - idx = find_sec(m, ".symtab"); - - if (!idx) { - pr_debug(MOD "WARN: no .symtab section found\n"); - return -1; - } - - symtab = &m->shdr[idx]; - - if (symtab->sh_entsize != sizeof(Elf_Sym)) { - pr_debug("Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize); - return -1; - } - - symbols = (Elf_Sym *) ((unsigned long) m->ehdr + symtab->sh_offset); - - sym_cnt = symtab->sh_size / symtab->sh_entsize; - - for (i = 0; i < sym_cnt; i++) { - if(!strcmp(get_symbol_str(m, i), name)) { - return ELF_ST_TYPE(symbols[i].st_info); - } - } - - return 0; -} - - - -/** - * @brief get the value of a symbol - * - * @return 1 if symbol has been found, 0 otherwise - */ - -static unsigned long get_symbol_value(const struct elf_module *m, - const char *name, unsigned long *value) - -{ - unsigned int i; - unsigned int idx; - size_t sym_cnt; - - Elf_Shdr *symtab; - Elf_Sym *symbols; - - - idx = find_sec(m, ".symtab"); - - if (!idx) { - pr_debug(MOD "WARN: no .symtab section found\n"); - return -1; - } - - symtab = &m->shdr[idx]; - - if (symtab->sh_entsize != sizeof(Elf_Sym)) { - pr_debug(MOD "Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize); - return -1; - } - - symbols = (Elf_Sym *) ((unsigned long) m->ehdr + symtab->sh_offset); - - sym_cnt = symtab->sh_size / symtab->sh_entsize; - - for (i = 0; i < sym_cnt; i++) { - if(!strcmp(get_symbol_str(m, i), name)) { - (*value) = symbols[i].st_value; - return 1; - } - } - - return 0; -} - -/** - * @brief dump the contents of .symtab - */ - -static int dump_symtab(struct elf_module *m) -{ - Elf_Shdr *symtab; - Elf_Sym *symbols; - - size_t sym_cnt; - unsigned int idx; - unsigned int i; - - - - idx = find_sec(m, ".symtab"); - - if (!idx) { - printk(MOD "WARN: no .symtab section found\n"); - return -1; - } - - symtab = &m->shdr[idx]; - - if (symtab->sh_entsize != sizeof(Elf_Sym)) { - printk(MOD "Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize); - return -1; - } - - symbols = (Elf_Sym *) ((unsigned long) m->ehdr + symtab->sh_offset); - - sym_cnt = symtab->sh_size / symtab->sh_entsize; - - - printk(MOD "\n" - MOD ".symtab contains %d entries\n" - MOD "============================\n" - MOD "\t[NUM]\t[VALUE]\t\t\t[SIZE]\t[TYPE]\t[NAME]\n", sym_cnt); - - - for (i = 0; i < sym_cnt; i++) { - - printk(MOD "\t%d\t%016lx\t%4ld", - i, - symbols[i].st_value, - symbols[i].st_size); - - switch (ELF_ST_TYPE(symbols[i].st_info)) { - case STT_NOTYPE : - printk("\tNOTYPE "); break; - case STT_OBJECT : - printk("\tOBJECT "); break; - case STT_FUNC : - printk("\tFUNC "); break; - case STT_SECTION : - printk("\tSECTION"); break; - case STT_FILE : - printk("\tFILE "); break; - case STT_COMMON : - printk("\tCOMMON "); break; - case STT_TLS : - printk("\tTLS "); break; - default: - printk("\tUNKNOWN"); break; - } - - printk("\t%-10s\n", get_symbol_str(m, i)); - - } - - return 0; -} - - - -/** - * @brief dump the contents of strtab - */ - -__attribute__((unused)) -static void dump_strtab(const struct elf_module *m) -{ - size_t i = 0; - - - if (!m->str) - return; - - - printk(MOD "\n.strtab:\n" - "============================\n" - "\t[OFF]\t[STR]\n"); - - while(i < m->sh_size) { - printk(MOD "\t[%d]\t%s\n", i, m->str + i); - i += strlen(m->str + i) + 1; - } - - printk(MOD "\n\n"); -} - - -/** - * @brief locate and set the ".shstrtab" section - * - * @return 0 if section header string table was not found, 1 otherwise - * - */ - -static int set_shstrtab(struct elf_module *m) -{ - size_t i; - - for (i = 0; i < m->ehdr->e_shnum; i++) { - - if (m->shdr[i].sh_type != SHT_STRTAB) - continue; - - /* section name index is not within table boundary, skip */ - if (m->shdr[i].sh_size < m->shdr[i].sh_name) - continue; - - m->sh_str = (((char *) m->ehdr) + m->shdr[i].sh_offset); - m->sh_size = m->shdr[i].sh_size; - - /* it's a string section and the size is ok, - * now make sure it is the right one */ - if (!strcmp(m->sh_str + m->shdr[i].sh_name, ".shstrtab")) - return 1; - } - - m->sh_str = NULL; - m->sh_size = 0; - - return 0; -} - -/** - * @brief locate and set the ".dynstr" section - * - * @return 0 if section header string table was not found, 1 otherwise - * - */ - -static int set_dynstr(struct elf_module *m) -{ - unsigned int idx; - - - idx = find_sec(m, ".dynstr"); - - if (idx) { - m->dyn_str = (((char *) m->ehdr) + m->shdr[idx].sh_offset); - m->dyn_size = m->shdr[idx].sh_size; - return 1; - } - - m->dyn_str = NULL; - m->dyn_size = 0; - - return 0; -} - - -/** - * @brief locate and set the ".strtab" section - * - * @return 0 if string table was not found, 1 otherwise - * - */ - -static int set_strtab(struct elf_module *m) -{ - unsigned int idx; - - - idx = find_sec(m, ".strtab"); - - if (idx) { - m->str = (((char *) m->ehdr) + m->shdr[idx].sh_offset); - m->str_size = m->shdr[idx].sh_size; - return 1; - } - - m->str = NULL; - m->str_size = 0; - - return 0; -} - - /** * @brief setup the module structure * + * @param m a struct elf_module + * * @return -1 on error */ @@ -622,6 +74,8 @@ static int setup_module(struct elf_module *m) { int i; + Elf_Shdr *shdr; + /* initialise module configuration */ m->pa = 0; @@ -629,47 +83,28 @@ static int setup_module(struct elf_module *m) m->size = 0; m->refcnt = 0; m->align = sizeof(void *); - m->dyn = NULL; - m->dyn_size = 0; m->sec = NULL; m->base = NULL; m->init = NULL; m->exit = NULL; - /* set section headers */ - if (m->ehdr->e_shoff) { - m->shdr = (Elf_Shdr *) (((char *) m->ehdr) + m->ehdr->e_shoff); - } else { - m->shdr = NULL; - pr_debug(MOD "ERR: no section header found\n"); - return -1; - } - - /* locate and set section header string table */ - if (!set_shstrtab(m)) - return -1; - - /* locate and set dynamic string table */ - if (!set_dynstr(m)) { - pr_debug(MOD "WARN: no dynamic string table found\n"); - } - - /* locate and set string table */ - if (!set_strtab(m)) - return -1; - + /* set up for relocatable object */ if (m->ehdr->e_type == ET_REL) { for (i = 0; i < m->ehdr->e_shnum; i++) { - if ((m->shdr[i].sh_flags & SHF_ALLOC)) { + shdr = elf_get_sec_by_idx(m->ehdr, i); + if (!shdr) + return -1; + + if (shdr->sh_flags & SHF_ALLOC) { pr_debug(MOD "Alloc section: %s, size %ld\n", - m->sh_str + m->shdr[i].sh_name, - m->shdr[i].sh_size); + elf_get_shstrtab_str(m->ehdr, i), + shdr->sh_size); - m->size += m->shdr[i].sh_size; + m->size += shdr->sh_size; - if (m->shdr[i].sh_addralign > m->align) { - m->align = m->shdr[i].sh_addralign; + if (shdr->sh_addralign > m->align) { + m->align = shdr->sh_addralign; pr_debug(MOD "align: %d\n", m->align); } @@ -677,11 +112,17 @@ static int setup_module(struct elf_module *m) } } - return 0; } +/** + * @brief load the run time sections of a module into memory + * + * @param m a struct elf_module + * + * @return 0 on success, -ENOMEM on error + */ static int module_load_mem(struct elf_module *m) { @@ -711,7 +152,7 @@ static int module_load_mem(struct elf_module *m) va_load = m->va; pa_load = m->pa; - m->num_sec = get_num_alloc_sections(m); + m->num_sec = elf_get_num_alloc_sections(m->ehdr); m->sec = (struct module_section *) kcalloc(sizeof(struct module_section), m->num_sec); @@ -723,11 +164,11 @@ static int module_load_mem(struct elf_module *m) while (1) { - idx = find_shdr_alloc(m, idx + 1); + idx = elf_find_shdr_alloc_idx(m->ehdr, idx + 1); if (!idx) break; - sec = get_sec(m, idx); + sec = elf_get_sec_by_idx(m->ehdr, idx); if (!sec->sh_size) /* don't need those */ @@ -735,7 +176,10 @@ static int module_load_mem(struct elf_module *m) s->size = sec->sh_size; - src = get_shstrtab_str(m, idx); + src = elf_get_shstrtab_str(m->ehdr, idx); + if (!src) + goto error; + s->name = kmalloc(strlen(src)); if (!s->name) @@ -787,6 +231,14 @@ error: } +/** + * @brief apply relocations to a module + * + * @param m a struct elf_module + * + * @return 0 on success, otherwise error + */ + static int module_relocate(struct elf_module *m) { unsigned int idx = 0; @@ -810,12 +262,12 @@ static int module_relocate(struct elf_module *m) while (1) { - idx = find_sec_type(m, SHT_RELA, idx + 1); + idx = elf_find_sec_idx_by_type(m->ehdr, SHT_RELA, idx + 1); if (!idx) break; - sec = get_sec(m, idx); + sec = elf_get_sec_by_idx(m->ehdr, idx); pr_debug(MOD "\n" MOD "Section Header info: %ld\n", sec->sh_info); @@ -834,10 +286,10 @@ static int module_relocate(struct elf_module *m) int reladdr; unsigned int symsec = ELF_R_SYM(relatab[i].r_info); - char *symstr = get_symbol_str(m, symsec); + char *symstr = elf_get_symbol_str(m->ehdr, symsec); struct module_section *s; struct module_section *text = find_mod_sec(m, ".text"); - + pr_debug(MOD "OFF: %08lx INF: %8lx ADD: %3ld LNK: %ld SEC: %d NAME: %s\n", relatab[i].r_offset, relatab[i].r_info, @@ -858,15 +310,15 @@ static int module_relocate(struct elf_module *m) symstr); - if (!(get_symbol_type(m, symstr) & STT_OBJECT)) { + if (!(elf_get_symbol_type(m->ehdr, symstr) & STT_OBJECT)) { pr_debug(MOD "\tERROR, object data resolution not yet implemented, symbol %s may not function as intended. If it is a variable, declare it static as a workaround\n", symstr); } - if (!(get_symbol_type(m, symstr) & (STT_FUNC | STT_OBJECT))) { + if (!(elf_get_symbol_type(m->ehdr, symstr) & (STT_FUNC | STT_OBJECT))) { pr_err(MOD "\tERROR, unresolved symbol %s\n", symstr); return -1; } - if (!get_symbol_value(m, symstr, &symval)) { + if (!elf_get_symbol_value(m->ehdr, symstr, &symval)) { pr_err(MOD "\tERROR, unresolved symbol %s\n", symstr); return -1; } @@ -881,7 +333,7 @@ static int module_relocate(struct elf_module *m) } else { /* no string, symtab entry is probably a section, try to identify it */ - char *secstr = get_shstrtab_str(m, symsec); + char *secstr = elf_get_shstrtab_str(m->ehdr, symsec); s = find_mod_sec(m, secstr); @@ -909,6 +361,13 @@ static int module_relocate(struct elf_module *m) } +/** + * @brief unload a module + * + * @param m a struct elf_module + * + */ + void module_unload(struct elf_module *m) { int i; @@ -929,6 +388,14 @@ void module_unload(struct elf_module *m) } +/** + * @brief load a module + * + * @param m a struct elf_module + * @param p the address where the module ELF file is located + * + * @return 0 on success, -1 on error + */ int module_load(struct elf_module *m, void *p) { @@ -965,13 +432,13 @@ int module_load(struct elf_module *m, void *p) _kmod.m[_kmod.cnt++] = m; - if (get_symbol_value(m, "_module_init", &symval)) + if (elf_get_symbol_value(m->ehdr, "_module_init", &symval)) m->init = (void *) (m->va + symval); else pr_warn(MOD "_module_init() not found\n"); - if (get_symbol_value(m, "_module_exit", &symval)) + if (elf_get_symbol_value(m->ehdr, "_module_exit", &symval)) m->exit = (void *) (m->va + symval); else pr_warn(MOD "_module_exit() not found\n"); @@ -997,6 +464,9 @@ error: } +/** + * @brief list all loaded modules + */ void modules_list_loaded(void) { @@ -1010,8 +480,8 @@ void modules_list_loaded(void) MOD "\n", (*m), (*m)->base); - dump_sections((*m)); - dump_symtab((*m)); + elf_dump_sections((*m)->ehdr); + elf_dump_symtab((*m)->ehdr); m++; } diff --git a/kernel/xentium.c b/kernel/xentium.c new file mode 100644 index 0000000..e1b09ba --- /dev/null +++ b/kernel/xentium.c @@ -0,0 +1,304 @@ +/** + * @file kernel/xentium.c + * + */ + + +#include <kernel/printk.h> +#include <kernel/err.h> +#include <kernel/xentium.h> +#include <kernel/kmem.h> +#include <kernel/kernel.h> +#include <asm-generic/swab.h> +#include <kernel/string.h> +#include <elf.h> + + + + + + + + + + +#define MSG "XEN: " + + + +/* if we need more space, this is how many entries we will add */ +#define KERNEL_REALLOC 10 +/* this is where we keep track of loaded modules */ +static struct { + struct xen_kernel **x; + int sz; + int cnt; +} _xen; + + + + +/** + * @brief setup the module structure + * + * @return -1 on error + */ + +static int xentium_setup_kernel(struct xen_kernel *m) +{ + int i; + + Elf_Shdr *shdr; + + + /* initialise module configuration */ + m->size = 0; + m->refcnt = 0; + m->align = sizeof(void *); + m->sec = NULL; + m->ep = m->ehdr->e_entry; + + + + for (i = 0; i < m->ehdr->e_shnum; i++) { + shdr = elf_get_sec_by_idx(m->ehdr, i); + if (!shdr) + return -1; + + if (shdr->sh_flags & SHF_ALLOC) { + printk(MSG "found alloc section: %s, size %ld\n", + elf_get_shstrtab_str(m->ehdr, i), + shdr->sh_size); + + m->size += shdr->sh_size; + + if (shdr->sh_addralign > m->align) { + m->align = shdr->sh_addralign; + printk(MSG "align: %d\n", m->align); + } + + } + } + + return 0; +} + + + +/** + * @brief check if this is a valid Xentium ELF binary + * @note this requires elf32-big instead of elf32-xentium in linker script + * target + */ + +int xentium_elf_header_check(Elf_Ehdr *ehdr) +{ + if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) { + pr_debug(MSG "swapping kernel ELF header endianess"); + elf_hdr_endianess_swap(ehdr); + } + + if (ehdr->e_shentsize != sizeof(Elf_Shdr)) + return -1; + + if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0)) + return -1; + + if (!(ehdr->e_ident[EI_MAG1] == ELFMAG1)) + return -1; + + if (!(ehdr->e_ident[EI_MAG2] == ELFMAG2)) + return -1; + + if (!(ehdr->e_ident[EI_MAG3] == ELFMAG3)) + return -1; + + if (!(ehdr->e_ident[EI_CLASS] == ELFCLASS32)) + if (!(ehdr->e_ident[EI_CLASS] == ELFCLASS64)) + return -1; + + + if (!(ehdr->e_ident[EI_VERSION] == EV_CURRENT)) + return -1; + +#if 0 + /* the Xentium toolchain cannot produce files with relocations, + * which is very sad... + */ + if (!(ehdr->e_type == ET_REL)) { + return -1; + } + + if(!ehdr->e_machine != XXX) + return -1; +#endif + + if (!(ehdr->e_version == EV_CURRENT)) + return -1; + + return 0; +} + + +/** + * @brief load a xentium kernel + * + * @note since xentium programs are not relocatable, this just dumps + * them wherever they say they want to be. The user is responsible for the + * proper memory configuration and offsets, I really can't do much about that at + * the moment, because I simply do not have the time to just work with the + * object files and do all relocations by hand, because that would also require + * me to take care of the Xentium's runtime wrapper code, which again would take + * more time that I can currently spare, but this would be the preferred + * solution. + */ + +static int xentium_load_kernel(struct xen_kernel *x) +{ + unsigned int idx = 0; + + char *src; + + Elf_Shdr *sec; + + struct xen_module_section *s; + + uint32_t *p; + + int i; + + + printk(MSG "\n" MSG "\n" + MSG "Loading kernel run-time sections\n"); + + x->num_sec = elf_get_num_alloc_sections(x->ehdr); + x->sec = (struct xen_module_section *) + kcalloc(sizeof(struct xen_module_section), x->num_sec); + + if (!x->sec) + goto error; + + s = x->sec; + + while (1) { + + idx = elf_find_shdr_alloc_idx(x->ehdr, idx + 1); + + + if (!idx) + break; + + sec = elf_get_sec_by_idx(x->ehdr, idx); + + if (!sec->sh_size) /* don't need those */ + continue; + + s->size = sec->sh_size; + + src = elf_get_shstrtab_str(x->ehdr, idx); + s->name = kmalloc(strlen(src)); + + if (!s->name) + goto error; + + strcpy(s->name, src); + + if (sec->sh_type & SHT_NOBITS) { + printk(MSG "\tZero segment %10s at %p size %ld\n", + s->name, (char *) sec->sh_addr, + sec->sh_size); + + bzero((void *) sec->sh_addr, s->size); + } else { + printk(MSG "\tcopy segment %10s from %p to %p size %ld\n", + s->name, + (char *) x->ehdr + sec->sh_offset, + (char *) sec->sh_addr, + sec->sh_size); + + memcpy((void *) sec->sh_addr, + (char *) x->ehdr + sec->sh_offset, + sec->sh_size); + + printk(MSG "\tadjust byte ordering\n"); + + p = (uint32_t *) sec->sh_addr; + for (i = 0; i < sec->sh_size / sizeof(uint32_t); i++) + p[i] = swab32(p[i]); + + + + } + + s->addr = sec->sh_addr; + + s++; + + if (s > &x->sec[x->num_sec]) { + printk(MSG "Error out of section memory\n"); + goto error; + } + } + + return 0; + +error: + if (x->sec) + for (idx = 0; idx < x->num_sec; idx++) + kfree(x->sec[idx].name); + + kfree(x->sec); + + return -ENOMEM; +} + + + +#include <asm-generic/swab.h> +int xentium_kernel_load(struct xen_kernel *x, void *p) +{ + unsigned long symval; + + + /* the ELF binary starts with the ELF header */ + x->ehdr = (Elf_Ehdr *) p; + + printk(MSG "Checking ELF header\n"); + + + + if (xentium_elf_header_check(x->ehdr)) + goto error; + + printk(MSG "Setting up module configuration\n"); + + if (xentium_setup_kernel(x)) + goto error; + + if (xentium_load_kernel(x)) + goto cleanup; + + + + if (_xen.cnt == _xen.sz) { + _xen.x = krealloc(_xen.x, (_xen.sz + KERNEL_REALLOC) * + sizeof(struct xen_kernel **)); + + bzero(&_xen.x[_xen.sz], sizeof(struct xen_kernel **) * + KERNEL_REALLOC); + _xen.sz += KERNEL_REALLOC; + } + + _xen.x[_xen.cnt++] = x; + + return 0; +cleanup: + printk("cleanup\n"); +#if 0 + xentium_kernel_unload(m); +#endif +error: + printk("error\n"); + return -1; +} + diff --git a/lib/Makefile b/lib/Makefile index a0d140f..9f50e2e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -4,3 +4,4 @@ lib-$(CONFIG_PAGE_MAP) += page.o lib-$(CONFIG_AR) += ar.o lib-$(CONFIG_CHUNK) += chunk.o lib-y += string.o +lib-y += elf.o diff --git a/lib/elf.c b/lib/elf.c new file mode 100644 index 0000000..a63e372 --- /dev/null +++ b/lib/elf.c @@ -0,0 +1,831 @@ +/** + * @file lib/elf.c + */ + + +#include <kernel/elf.h> +#include <kernel/string.h> +#include <kernel/printk.h> + +#include <asm-generic/swab.h> + +#define MSG "ELF: " + + +/** + * @brief get the base of the ELF section header(s) + * + * @param ehdr an Elf_Ehdr + * + * return a Elf_Shdr or NULL if not found + */ + +Elf_Shdr *elf_get_shdr(const Elf_Ehdr *ehdr) +{ + Elf_Shdr *shdr = NULL; + + if (ehdr->e_shoff) + shdr = (Elf_Shdr *) (((char *) ehdr) + ehdr->e_shoff); + + + return shdr; +} + + +/** + * @brief find section headers marked ALLOC by index + * + * @param ehdr an Elf_Ehdr + * + * + * @param offset a offset into the table (to locate multiple identical types) + * + * @return section index or 0 if not found + */ + +size_t elf_find_shdr_alloc_idx(const Elf_Ehdr *ehdr, const size_t offset) +{ + size_t i; + + Elf_Shdr *shdr; + + + shdr = elf_get_shdr(ehdr); + if (!shdr) + return 0; + + + for (i = offset; i < ehdr->e_shnum; i++) { + if ((shdr[i].sh_flags & SHF_ALLOC)) + return i; + } + + return 0; +} + + +/** + * @brief return a section header by index + * + * @param ehdr an Elf_Ehdr + * + * @param idx the section index + * + * @return NULL if entry not found, pointer to entry otherwise + */ + +Elf_Shdr *elf_get_sec_by_idx(const Elf_Ehdr *ehdr, const size_t idx) +{ + Elf_Shdr *shdr; + + + if (idx >= ehdr->e_shnum) + return NULL; + + shdr = elf_get_shdr(ehdr); + if (!shdr) + return NULL; + + return &shdr[idx]; +} + + +/** + * @brief locate the ".shstrtab" section + * + * @param ehdr an Elf_Ehdr + * + * @return the section header or NULL if not found + * + */ + +Elf_Shdr *elf_get_sec_shstrtab(const Elf_Ehdr *ehdr) +{ + size_t i; + + char *sh_str; + + Elf_Shdr *shdr; + + + shdr = elf_get_shdr(ehdr); + if (!shdr) + return NULL; + + + for (i = 0; i < ehdr->e_shnum; i++) { + + if (shdr[i].sh_type != SHT_STRTAB) + continue; + + /* section name index is not within table boundary, skip */ + if (shdr[i].sh_size < shdr[i].sh_name) + continue; + + sh_str = (((char *) ehdr) + shdr[i].sh_offset); + + /* it's a string section and the size is ok, + * now make sure it is the right one */ + if (!strcmp(sh_str + shdr[i].sh_name, ".shstrtab")) + return &shdr[i]; + } + + return NULL; +} + + +/** + * @brief in-place swap the endianess of an ELF header + * + * @param ehdr an Elf_Ehdr + */ + +void elf_hdr_endianess_swap(Elf_Ehdr *ehdr) +{ + uint32_t i; + uint32_t len; + + uint32_t *p; + + Elf_Shdr *shdr; + Elf_Phdr *phdr; + + + + /* endianess is a factor from e_type onwards */ + + ehdr->e_type = swab16(ehdr->e_type); + ehdr->e_machine = swab16(ehdr->e_machine); + ehdr->e_version = swab32(ehdr->e_version); + ehdr->e_entry = swab32(ehdr->e_entry); + ehdr->e_phoff = swab32(ehdr->e_phoff); + ehdr->e_shoff = swab32(ehdr->e_shoff); + ehdr->e_flags = swab32(ehdr->e_flags); + ehdr->e_ehsize = swab16(ehdr->e_ehsize); + ehdr->e_phentsize = swab16(ehdr->e_phentsize); + ehdr->e_phnum = swab16(ehdr->e_phnum); + ehdr->e_shentsize = swab16(ehdr->e_shentsize); + ehdr->e_shnum = swab16(ehdr->e_shnum); + ehdr->e_shstrndx = swab16(ehdr->e_shstrndx); + + /* everything after is in 32 bit words */ + + phdr = (Elf_Phdr *) ((char *) ehdr + ehdr->e_phoff); + + for (i = 0; i < ehdr->e_phnum; i++) { + phdr[i].p_type = swab32(phdr[i].p_type); + phdr[i].p_flags = swab32(phdr[i].p_flags); + phdr[i].p_offset = swab32(phdr[i].p_offset); + phdr[i].p_vaddr = swab32(phdr[i].p_vaddr); + phdr[i].p_paddr = swab32(phdr[i].p_paddr); + phdr[i].p_filesz = swab32(phdr[i].p_filesz); + phdr[i].p_memsz = swab32(phdr[i].p_memsz); + phdr[i].p_align = swab32(phdr[i].p_align); + } + + shdr = (Elf_Shdr *) ((char *) ehdr + ehdr->e_shoff); + + for (i = 0; i < ehdr->e_shnum; i++) { + shdr[i].sh_name = swab32(shdr[i].sh_name); + shdr[i].sh_type = swab32(shdr[i].sh_type); + shdr[i].sh_flags = swab32(shdr[i].sh_flags); + shdr[i].sh_addr = swab32(shdr[i].sh_addr); + shdr[i].sh_offset = swab32(shdr[i].sh_offset); + shdr[i].sh_size = swab32(shdr[i].sh_size); + shdr[i].sh_link = swab32(shdr[i].sh_link); + shdr[i].sh_info = swab32(shdr[i].sh_info); + shdr[i].sh_addralign = swab32(shdr[i].sh_addralign); + shdr[i].sh_entsize = swab32(shdr[i].sh_entsize); + } +} + +/** + * @brief get the address of the section header string table + * + * @param ehdr an Elf_Ehdr + * + * @return the address of the section header string table or NULL if not found + */ + +char *elf_get_shstrtab(const Elf_Ehdr *ehdr) +{ + char *sh_str; + + Elf_Shdr *shdr; + + + shdr = elf_get_sec_shstrtab(ehdr); + if (!shdr) + return NULL; + + + sh_str = (((char *) ehdr) + shdr->sh_offset); + + return sh_str; +} + + +/** + * @brief get an entry in the .shstrtab + * + * @param ehdr an Elf_Ehdr + * + * @param idx the section index + * + * @return pointer to the start of the string or NULL if not found + */ + +char *elf_get_shstrtab_str(const Elf_Ehdr *ehdr, size_t idx) +{ + char *sh_str; + + Elf_Shdr *shdr; + + + + if (idx >= ehdr->e_shnum) + return NULL; + + shdr = elf_get_shdr(ehdr); + if (!shdr) + return NULL; + + sh_str = elf_get_shstrtab(ehdr); + if (!sh_str) + return NULL; + + + return sh_str + shdr[idx].sh_name; +} + + + +/** + * @brief find an elf section by name + * + * @return section index or 0 if not found + */ + +Elf_Shdr *elf_find_sec(const Elf_Ehdr *ehdr, const char *name) +{ + size_t i; + + char *sh_str; + + Elf_Shdr *shdr; + + + shdr = elf_get_sec_shstrtab(ehdr); + if (!shdr) + return NULL; + + sh_str = ((char *) ehdr + shdr->sh_offset); + + for (i = 1; i < ehdr->e_shnum; i++) { + if (!strcmp(sh_str + shdr[i].sh_name, name)) + return &shdr[i]; + } + + return NULL; +} + + +/** + * @brief get the address of the string table + * + * @param ehdr an Elf_Ehdr + * + * @return the address of the string table or NULL if not found + */ + +char *elf_get_strtab(const Elf_Ehdr *ehdr) +{ + char *sh_str; + + Elf_Shdr *shdr; + + + shdr = elf_find_sec(ehdr, ".strtab"); + if (!shdr) + return NULL; + + + sh_str = (((char *) ehdr) + shdr->sh_offset); + + return sh_str; +} + + +/** + * @brief get an entry in the .strtab + * + * @param ehdr an Elf_Ehdr + * + * @param idx the entry index + * + * @return pointer to the start of the string or NULL if not found + */ + +char *elf_get_strtab_str(const Elf_Ehdr *ehdr, size_t idx) +{ + char *str; + + Elf_Shdr *shdr; + + + + if (idx >= ehdr->e_shnum) + return NULL; + + shdr = elf_get_shdr(ehdr); + if (!shdr) + return NULL; + + str = elf_get_strtab(ehdr); + if (!str) + return NULL; + + + return str + shdr[idx].sh_name; +} + + +/** + * @brief get the address of the dynamic string table + * + * @param ehdr an Elf_Ehdr + * + * @return the address of the string table or NULL if not found + */ + +char *elf_get_dynstr(const Elf_Ehdr *ehdr) +{ + char *dyn_str; + + Elf_Shdr *shdr; + + + shdr = elf_find_sec(ehdr, ".dynstr"); + if (!shdr) + return NULL; + + + dyn_str = (((char *) ehdr) + shdr->sh_offset); + + return dyn_str; +} + + +/** + * @brief get an entry in the .strtab + * + * @param ehdr an Elf_Ehdr + * + * @param idx the entry index + * + * @return pointer to the start of the string or NULL if not found + */ + +char *elf_get_dynstr_str(const Elf_Ehdr *ehdr, size_t idx) +{ + char *sh_str; + + Elf_Shdr *shdr; + + + + if (idx >= ehdr->e_shnum) + return NULL; + + shdr = elf_get_shdr(ehdr); + if (!shdr) + return NULL; + + sh_str = elf_get_dynstr(ehdr); + if (!sh_str) + return NULL; + + + return sh_str + shdr[idx].sh_name; +} + + +/** + * @brief get the name of a symbol in .symtab with a given index + * + * @param ehdr an Elf_Ehdr + * + * @param idx the symbol index + * + * @return pointer to the start of the string or NULL if not found + */ + +char *elf_get_symbol_str(const Elf_Ehdr *ehdr, size_t idx) +{ + Elf_Shdr *symtab; + Elf_Sym *symbols; + + + symtab = elf_find_sec(ehdr, ".symtab"); + if (!symtab) + return NULL; + + symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset); + + if (idx < symtab->sh_size / symtab->sh_entsize) + return elf_get_strtab(ehdr) + symbols[idx].st_name; + + return NULL; +} + + +/** + * @brief get the value of a symbol + * + * @param ehdr an Elf_Ehdr + * + * @param name the name of the symbol + * + * @param[out] value the value of the symbol + * + * @return 1 if symbol has been found, 0 otherwise + */ + +unsigned long elf_get_symbol_value(const Elf_Ehdr *ehdr, + const char *name, unsigned long *value) + +{ + unsigned int i; + unsigned int idx; + size_t sym_cnt; + + Elf_Shdr *symtab; + Elf_Sym *symbols; + + + symtab = elf_find_sec(ehdr, ".symtab"); + + if (!symtab) { + pr_debug(MSG "WARN: no .symtab section found\n"); + return -1; + } + + if (symtab->sh_entsize != sizeof(Elf_Sym)) { + pr_debug(MSG "Error %d != %ld\n", + sizeof(Elf_Sym), symtab->sh_entsize); + return -1; + } + + symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset); + + sym_cnt = symtab->sh_size / symtab->sh_entsize; + + for (i = 0; i < sym_cnt; i++) { + if(!strcmp(elf_get_symbol_str(ehdr, i), name)) { + (*value) = symbols[i].st_value; + return 1; + } + } + + return 0; +} + + +/** + * @brief get the ELF type of a symbol + * + * @param ehdr an Elf_Ehdr + * + * @param name the name of the symbol + * + * @return the symbol type or 0 on error or if not found + */ + +unsigned long elf_get_symbol_type(const Elf_Ehdr *ehdr, const char *name) +{ + unsigned int i; + size_t sym_cnt; + + Elf_Shdr *symtab; + Elf_Sym *symbols; + + + symtab = elf_find_sec(ehdr, ".symtab"); + + if (!symtab) { + pr_debug(MSG "WARN: no .symtab section found\n"); + return 0; + } + + if (symtab->sh_entsize != sizeof(Elf_Sym)) { + pr_debug("Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize); + return 0; + } + + symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset); + + sym_cnt = symtab->sh_size / symtab->sh_entsize; + + for (i = 0; i < sym_cnt; i++) { + if(!strcmp(elf_get_symbol_str(ehdr, i), name)) + return ELF_ST_TYPE(symbols[i].st_info); + } + + return 0; +} + + +/** + * @brief find an elf section index by type + * + * @param ehdr an Elf_Ehdr + * + * @param sh_type the section type to look for + * + * @param offset a offset into the table (to locate multiple identical types) + * + * @return section index or 0 if not found + * + */ + +size_t elf_find_sec_idx_by_type(const Elf_Ehdr *ehdr, + const uint32_t sh_type, + const size_t offset) +{ + size_t i; + + Elf_Shdr *shdr; + + + for (i = offset; i < ehdr->e_shnum; i++) { + shdr = elf_get_sec_by_idx(ehdr, i); + if (!shdr) + return 0; + if (sh_type == shdr->sh_type) + return i; + } + + return 0; +} + + +/** + * @brief get number of sections marked ALLOC with size > 0 + * + * @param ehdr an Elf_Ehdr + * + * @return number of ALLOC sections + */ + +size_t elf_get_num_alloc_sections(const Elf_Ehdr *ehdr) +{ + size_t i; + size_t cnt = 0; + + Elf_Shdr *shdr; + + + for (i = 0; i <ehdr->e_shnum; i++) { + shdr = elf_get_sec_by_idx(ehdr, i); + if ((shdr->sh_flags & SHF_ALLOC)) + if (shdr->sh_size) + cnt++; + } + + return cnt; +} + + +/** + * @brief get the number of entries in a dynamic section + * + * @param ehdr an Elf_Ehdr + * + * @return the number of entries in a dynamic section + */ + +size_t elf_get_num_dyn_entries(const Elf_Ehdr *ehdr) +{ + Elf_Shdr *shdr; + + + shdr = elf_find_sec(ehdr, ".dyn"); + if (!shdr) + return 0; + + + return shdr->sh_size / sizeof(Elf_Dyn); +} + + +/** + * @brief find a dynamic entry by tag + * + * @param offset a offset into the table (to locate multiple identical types) + * + * @return NULL if entry not found, pointer to entry otherwise + * + */ +Elf_Dyn *elf_find_dyn(const Elf_Ehdr *ehdr, + const unsigned long d_tag, + const unsigned int offset) +{ + size_t i; + + Elf_Shdr *shdr; + + Elf_Dyn *dyn; + + + shdr = elf_find_sec(ehdr, ".dyn"); + + dyn = (Elf_Dyn *) (((char *) ehdr) + shdr->sh_offset); + + for (i = offset; i < elf_get_num_dyn_entries(ehdr); i++) + if (d_tag == dyn[i].d_tag) + return &dyn[i]; + + return NULL; +} + + + + +/** + * @brief dump the contents of .strtab + */ + +void elf_dump_strtab(const Elf_Ehdr *ehdr) +{ + size_t i = 0; + + char *s; + + + printk(MSG "\n.strtab:\n" + "============================\n" + "\t[OFF]\t[STR]\n"); + + while((s = elf_get_strtab_str(ehdr, i++))) + printk(MSG "\t[%d]\t%s\n", i, s); + + printk(MSG "\n\n"); +} + + +/** + * @brief dump the contents of .symtab + */ + +void elf_dump_symtab(const Elf_Ehdr *ehdr) +{ + Elf_Shdr *symtab; + Elf_Sym *symbols; + + size_t sym_cnt; + unsigned int idx; + unsigned int i; + + + + symtab = elf_find_sec(ehdr, ".symtab"); + + if (!symtab) { + printk(MSG "WARN: no .symtab section found\n"); + return; + } + + + if (symtab->sh_entsize != sizeof(Elf_Sym)) { + printk(MSG "Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize); + return; + } + + symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset); + + sym_cnt = symtab->sh_size / symtab->sh_entsize; + + + printk(MSG "\n" + MSG ".symtab contains %d entries\n" + MSG "============================\n" + MSG "\t[NUM]\t[VALUE]\t\t\t[SIZE]\t[TYPE]\t[NAME]\n", sym_cnt); + + + for (i = 0; i < sym_cnt; i++) { + + printk(MSG "\t%d\t%016lx\t%4ld", + i, + symbols[i].st_value, + symbols[i].st_size); + + switch (ELF_ST_TYPE(symbols[i].st_info)) { + case STT_NOTYPE : + printk("\tNOTYPE "); break; + case STT_OBJECT : + printk("\tOBJECT "); break; + case STT_FUNC : + printk("\tFUNC "); break; + case STT_SECTION : + printk("\tSECTION"); break; + case STT_FILE : + printk("\tFILE "); break; + case STT_COMMON : + printk("\tCOMMON "); break; + case STT_TLS : + printk("\tTLS "); break; + default: + printk("\tUNKNOWN"); break; + } + + printk("\t%-10s\n", elf_get_symbol_str(ehdr, i)); + + } +} + +/** + * @brief dump the name of all elf sections + */ + +void elf_dump_sections(const Elf_Ehdr *ehdr) +{ + size_t i; + + Elf_Shdr *shdr; + + + printk(MSG "SECTIONS:\n" + MSG "============================\n" + MSG "\t[NUM]\t[NAME]\t\t\t[TYPE]\t\t[SIZE]\t[ENTSZ]\t[FLAGS]\n" + ); + + + for (i = 0; i < ehdr->e_shnum; i++) { + + shdr = elf_get_sec_by_idx(ehdr, i); + printk(MSG "\t%d\t%-20s", i, elf_get_shstrtab_str(ehdr, i)); + + switch (shdr->sh_type) { + case SHT_NULL: + printk("%-10s", "\tNULL"); + break; + case SHT_PROGBITS: + printk("%-10s", "\tPROGBITS"); + break; + case SHT_SYMTAB: + printk("%-10s", "\tSYMTAB"); + break; + case SHT_STRTAB: + printk("%-10s", "\tSTRTAB"); + break; + case SHT_RELA : + printk("%-10s", "\tRELA"); + break; + case SHT_HASH : + printk("%-10s", "\tHASH"); + break; + case SHT_DYNAMIC: + printk("%-10s", "\tDYNAMIC"); + break; + case SHT_NOTE : + printk("%-10s", "\tNOTE"); + break; + case SHT_NOBITS: + printk("%-10s", "\tNOBITS"); + break; + case SHT_REL : + printk("%-10s", "\tREL"); + break; + case SHT_SHLIB : + printk("%-10s", "\tSHLIB"); + break; + case SHT_DYNSYM: + printk("%-10s", "\tDYNSYM"); + break; + case SHT_NUM : + printk("%-10s", "\tNUM"); + break; + default: + printk("%-10s", "\tOTHER"); + break; + } + + printk("\t%ld\t%ld\t", shdr->sh_size, shdr->sh_entsize); + + if (shdr->sh_flags & SHF_WRITE) + printk("WRITE "); + if (shdr->sh_flags & SHF_ALLOC) + printk("ALLOC "); + if (shdr->sh_flags & SHF_EXECINSTR) + printk("EXECINSTR "); + if (shdr->sh_flags & SHF_TLS) + printk("TLS "); + if (shdr->sh_flags & SHF_MASKPROC) + printk("MASKPROC "); + + printk(MSG "\n"); + + } + +} + diff --git a/lib/string.c b/lib/string.c index c1d537e..3f08b9d 100644 --- a/lib/string.c +++ b/lib/string.c @@ -153,6 +153,57 @@ void *memcpy(void *dest, const void *src, size_t n) EXPORT_SYMBOL(memcpy); +/** + * @brief copy a '\0' terminated string + * + * @param dest the destination of the string + * @param src the source of string + * + * @return a pointer to dest + * + * @note strings may not overlap + * + */ + +char *strcpy(char *dest, const char *src) +{ + char *tmp; + + + tmp = dest; + + while ((*dest++ = *src++) != '\0'); + + return tmp; +} +EXPORT_SYMBOL(strcpy); + + + +/** + * @brief set the first n bytes of the area starting at s to zero (bytes + * containing '\0') + * + * @param s the start of the area + * + * @param n the number of bytes to set to zero + * + */ + +void bzero(void *s, size_t n) +{ + char *c; + + + c = (char *) s; + + while (n--) { + (*c) = '\0'; + c++; + } +} +EXPORT_SYMBOL(bzero); + #include <stdarg.h> -- GitLab