Skip to content

Commit

Permalink
feat(x86_64): kernel symbols reading
Browse files Browse the repository at this point in the history
  • Loading branch information
llenotre committed Oct 18, 2024
1 parent 626ece1 commit 1b0cfd9
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 39 deletions.
36 changes: 25 additions & 11 deletions kernel/src/elf/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -29,21 +29,35 @@ 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<HashMap<&'static [u8], ELF32Sym>> = unsafe { OnceInit::new() };
static SYMBOLS: OnceInit<HashMap<&'static [u8], KernSym>> = unsafe { OnceInit::new() };

/// Returns an iterator over the kernel's ELF sections.
pub fn sections() -> impl Iterator<Item = &'static ELF32SectionHeader> {
pub fn sections() -> impl Iterator<Item = &'static KernSectionHeader> {
let boot_info = multiboot::get_boot_info();
(0..boot_info.elf_num).map(|i| get_section_by_offset(i).unwrap())
}

/// 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;
Expand All @@ -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();
Expand All @@ -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<Item = &'static ELF32Sym> {
pub fn symbols() -> impl Iterator<Item = &'static KernSym> {
let symtab = sections()
.find(|section| section.sh_type == SHT_SYMTAB)
.unwrap();
Expand All @@ -93,14 +107,14 @@ pub fn symbols() -> impl Iterator<Item = &'static ELF32Sym> {
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()
Expand Down Expand Up @@ -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)
}

Expand Down
40 changes: 20 additions & 20 deletions kernel/src/elf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
5 changes: 3 additions & 2 deletions kernel/src/elf/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub trait Relocation {
user: bool,
) -> Result<(), RelocationError>
where
F: FnOnce(u32, usize) -> Option<u32>,
F: FnOnce(u32, usize) -> Option<usize>,
{
let got_off = got.map(|sym| sym.st_value as usize).unwrap_or(0);
// The address of the GOT
Expand All @@ -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)?
Expand Down Expand Up @@ -213,4 +213,5 @@ macro_rules! rel_impl {
}

rel_impl!(ELF32Rel, ELF32Rela);
#[cfg(target_arch = "x86_64")]
rel_impl!(ELF64Rel, ELF64Rela);
2 changes: 1 addition & 1 deletion kernel/src/memory/vmem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
8 changes: 4 additions & 4 deletions kernel/src/module/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ pub mod version;
use crate::{
elf,
elf::{
kernel::KernSym,
parser::ELFParser,
relocation::{ELF32Rel, ELF32Rela, Relocation, GOT_SYM},
ELF32Sym,
},
};
use core::{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/process/exec/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit 1b0cfd9

Please sign in to comment.