diff --git a/kernel/src/elf/kernel.rs b/kernel/src/elf/kernel.rs index 215475ca..043c2ae2 100644 --- a/kernel/src/elf/kernel.rs +++ b/kernel/src/elf/kernel.rs @@ -18,7 +18,7 @@ //! Functions to explore the kernel's ELF structures. -use super::{ELF32SectionHeader, ELF32Sym, SHT_SYMTAB}; +use super::SHT_SYMTAB; use crate::{ memory::{PhysAddr, VirtAddr}, multiboot, @@ -29,13 +29,27 @@ use utils::{ lock::once::OnceInit, }; +/// A kernel ELF section header. +#[cfg(target_arch = "x86")] +pub type KernSectionHeader = super::ELF32SectionHeader; +/// A kernel ELF section header. +#[cfg(target_arch = "x86_64")] +pub type KernSectionHeader = super::ELF64SectionHeader; + +/// A kernel ELF symbol. +#[cfg(target_arch = "x86")] +pub type KernSym = super::ELF32Sym; +/// A kernel ELF symbol. +#[cfg(target_arch = "x86_64")] +pub type KernSym = super::ELF64Sym; + /// A reference to the strtab. -static STRTAB: OnceInit<&'static ELF32SectionHeader> = unsafe { OnceInit::new() }; +static STRTAB: OnceInit<&'static KernSectionHeader> = unsafe { OnceInit::new() }; /// Name-to-symbol map for the kernel. -static SYMBOLS: OnceInit> = unsafe { OnceInit::new() }; +static SYMBOLS: OnceInit> = unsafe { OnceInit::new() }; /// Returns an iterator over the kernel's ELF sections. -pub fn sections() -> impl Iterator { +pub fn sections() -> impl Iterator { let boot_info = multiboot::get_boot_info(); (0..boot_info.elf_num).map(|i| get_section_by_offset(i).unwrap()) } @@ -43,7 +57,7 @@ pub fn sections() -> impl Iterator { /// Returns a reference to the `n`th kernel section. /// /// If the section does not exist, the function returns `None`. -pub fn get_section_by_offset(n: u32) -> Option<&'static ELF32SectionHeader> { +pub fn get_section_by_offset(n: u32) -> Option<&'static KernSectionHeader> { let boot_info = multiboot::get_boot_info(); if n < boot_info.elf_num { let offset = n as usize * boot_info.elf_entsize as usize; @@ -60,7 +74,7 @@ pub fn get_section_by_offset(n: u32) -> Option<&'static ELF32SectionHeader> { /// Returns the name of the given kernel ELF section. /// /// If the name of the symbol could not be found, the function returns `None`. -pub fn get_section_name(section: &ELF32SectionHeader) -> Option<&'static [u8]> { +pub fn get_section_name(section: &KernSectionHeader) -> Option<&'static [u8]> { let boot_info = multiboot::get_boot_info(); // `unwrap` cannot fail because the ELF will always have this section let names_section = get_section_by_offset(boot_info.elf_shndx).unwrap(); @@ -77,12 +91,12 @@ pub fn get_section_name(section: &ELF32SectionHeader) -> Option<&'static [u8]> { /// `name` is the name of the required section. /// /// If the section doesn't exist, the function returns `None`. -pub fn get_section_by_name(name: &[u8]) -> Option<&'static ELF32SectionHeader> { +pub fn get_section_by_name(name: &[u8]) -> Option<&'static KernSectionHeader> { sections().find(|s| get_section_name(s) == Some(name)) } /// Returns an iterator over the kernel's ELF symbols. -pub fn symbols() -> impl Iterator { +pub fn symbols() -> impl Iterator { let symtab = sections() .find(|section| section.sh_type == SHT_SYMTAB) .unwrap(); @@ -93,14 +107,14 @@ pub fn symbols() -> impl Iterator { let symbols_count = (symtab.sh_size / symtab.sh_entsize) as usize; (0..symbols_count).map(move |i| { let off = i * symtab.sh_entsize as usize; - unsafe { &*(begin.add(off) as *const ELF32Sym) } + unsafe { &*(begin.add(off) as *const KernSym) } }) } /// Returns the name of the given kernel ELF symbol. /// /// If the name of the symbol could not be found, the function returns `None`. -pub fn get_symbol_name(symbol: &ELF32Sym) -> Option<&'static [u8]> { +pub fn get_symbol_name(symbol: &KernSym) -> Option<&'static [u8]> { let ptr = PhysAddr(STRTAB.get().sh_addr as usize + symbol.st_name as usize) .kernel_to_virtual() .unwrap() @@ -129,7 +143,7 @@ pub fn get_function_name(inst: VirtAddr) -> Option<&'static [u8]> { /// `name` is the name of the symbol to get. /// /// If the symbol doesn't exist, the function returns `None`. -pub fn get_symbol_by_name(name: &[u8]) -> Option<&'static ELF32Sym> { +pub fn get_symbol_by_name(name: &[u8]) -> Option<&'static KernSym> { SYMBOLS.get().get(name) } diff --git a/kernel/src/elf/mod.rs b/kernel/src/elf/mod.rs index 071189ad..0c77b35b 100644 --- a/kernel/src/elf/mod.rs +++ b/kernel/src/elf/mod.rs @@ -111,39 +111,39 @@ pub const PF_W: u32 = 0x2; pub const PF_R: u32 = 0x4; /// The section header is inactive. -pub const SHT_NULL: u32 = 0x00000000; +pub const SHT_NULL: u32 = 0x0; /// The section holds information defined by the program. -pub const SHT_PROGBITS: u32 = 0x00000001; +pub const SHT_PROGBITS: u32 = 0x1; /// The section holds a symbol table. -pub const SHT_SYMTAB: u32 = 0x00000002; +pub const SHT_SYMTAB: u32 = 0x2; /// the section holds a string table. -pub const SHT_STRTAB: u32 = 0x00000003; +pub const SHT_STRTAB: u32 = 0x3; /// The section holds relocation entries with explicit attends. -pub const SHT_RELA: u32 = 0x00000004; +pub const SHT_RELA: u32 = 0x4; /// The section holds a symbol hash table. -pub const SHT_HASH: u32 = 0x00000005; +pub const SHT_HASH: u32 = 0x5; /// The section holds information for dynamic linking. -pub const SHT_DYNAMIC: u32 = 0x00000006; +pub const SHT_DYNAMIC: u32 = 0x6; /// The section holds information that marks the file in some way. -pub const SHT_NOTE: u32 = 0x00000007; +pub const SHT_NOTE: u32 = 0x7; /// The section is empty but contains information in its offset. -pub const SHT_NOBITS: u32 = 0x00000008; +pub const SHT_NOBITS: u32 = 0x8; /// The section holds relocation entries without explicit attends. -pub const SHT_REL: u32 = 0x00000009; +pub const SHT_REL: u32 = 0x9; /// Reserved section type. -pub const SHT_SHLIB: u32 = 0x0000000a; +pub const SHT_SHLIB: u32 = 0xa; /// The section holds a symbol table. -pub const SHT_DYNSYM: u32 = 0x0000000b; +pub const SHT_DYNSYM: u32 = 0xb; -/// The section contains writable data. -pub const SHF_WRITE: u32 = 0x00000001; -/// The section occupies memory during execution. -pub const SHF_ALLOC: u32 = 0x00000002; -/// The section contains executable machine instructions. -pub const SHF_EXECINSTR: u32 = 0x00000004; -/// Thread-Local Storage (TLS) section. +/// Section flag: Contains writable data. +pub const SHF_WRITE: u32 = 0x1; +/// Section flag: Occupies memory during execution. +pub const SHF_ALLOC: u32 = 0x2; +/// Section flag: Contains executable machine instructions. +pub const SHF_EXECINSTR: u32 = 0x4; +/// Section flag: Thread-Local Storage (TLS) section. pub const SHF_TLS: u32 = 0x400; -/// All bits included in this mask are reserved for processor-specific +/// Section flag: All bits included in this mask are reserved for processor-specific /// semantics. pub const SHF_MASKPROC: u32 = 0xf0000000; diff --git a/kernel/src/elf/relocation.rs b/kernel/src/elf/relocation.rs index ec4bdecf..a2ef3f5a 100644 --- a/kernel/src/elf/relocation.rs +++ b/kernel/src/elf/relocation.rs @@ -68,7 +68,7 @@ pub trait Relocation { user: bool, ) -> Result<(), RelocationError> where - F: FnOnce(u32, usize) -> Option, + F: FnOnce(u32, usize) -> Option, { let got_off = got.map(|sym| sym.st_value as usize).unwrap_or(0); // The address of the GOT @@ -78,7 +78,7 @@ pub trait Relocation { // The offset in the PLT entry for the symbol let plt_offset = 0usize; // TODO // The value of the symbol - let sym_val = get_sym(rel_section.sh_link, self.get_sym()).map(|val| val as usize); + let sym_val = get_sym(rel_section.sh_link, self.get_sym()); let value = match self.get_type() { elf::R_386_32 => sym_val .ok_or(RelocationError)? @@ -213,4 +213,5 @@ macro_rules! rel_impl { } rel_impl!(ELF32Rel, ELF32Rela); +#[cfg(target_arch = "x86_64")] rel_impl!(ELF64Rel, ELF64Rela); diff --git a/kernel/src/memory/vmem/mod.rs b/kernel/src/memory/vmem/mod.rs index 68494ea7..d673bcc7 100644 --- a/kernel/src/memory/vmem/mod.rs +++ b/kernel/src/memory/vmem/mod.rs @@ -402,7 +402,7 @@ pub(crate) fn init() -> AllocResult<()> { // Make the kernel's code read-only let iter = elf::kernel::sections().filter(|s| s.sh_addralign as usize == PAGE_SIZE); for section in iter { - let write = section.sh_flags & elf::SHF_WRITE != 0; + let write = section.sh_flags as u32 & elf::SHF_WRITE != 0; let user = elf::kernel::get_section_name(section) == Some(b".user"); let mut flags = x86::FLAG_GLOBAL; if write { diff --git a/kernel/src/module/mod.rs b/kernel/src/module/mod.rs index b5ad9245..cf49bea2 100644 --- a/kernel/src/module/mod.rs +++ b/kernel/src/module/mod.rs @@ -33,9 +33,9 @@ pub mod version; use crate::{ elf, elf::{ + kernel::KernSym, parser::ELFParser, relocation::{ELF32Rel, ELF32Rela, Relocation, GOT_SYM}, - ELF32Sym, }, }; use core::{ @@ -138,7 +138,7 @@ impl Module { /// `name` is the name of the symbol to look for. /// /// If the symbol doesn't exist, the function returns `None`. - fn resolve_symbol(name: &[u8]) -> Option<&ELF32Sym> { + fn resolve_symbol(name: &[u8]) -> Option<&KernSym> { // The symbol on the kernel side let kernel_sym = elf::kernel::get_symbol_by_name(name)?; // TODO check symbols from other loaded modules @@ -226,9 +226,9 @@ impl Module { ); return None; }; - Some(other_sym.st_value) + Some(other_sym.st_value as usize) } else { - Some(load_base as u32 + sym.st_value) + Some(load_base as usize + sym.st_value as usize) } }; let got_sym = parser.get_symbol_by_name(GOT_SYM); diff --git a/kernel/src/process/exec/elf.rs b/kernel/src/process/exec/elf.rs index 256a4044..6d8aea6a 100644 --- a/kernel/src/process/exec/elf.rs +++ b/kernel/src/process/exec/elf.rs @@ -595,7 +595,7 @@ impl<'s> ELFExecutor<'s> { let section = elf.get_section_by_index(sym_section as _)?; let sym = elf.get_symbol_by_index(section, sym as _)?; if sym.is_defined() { - Some(load_base as u32 + sym.st_value) + Some(load_base as usize + sym.st_value as usize) } else { None }