-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Exposes kernel page size via ELF note (#934)
- Loading branch information
1 parent
30b712b
commit 0bd471b
Showing
12 changed files
with
238 additions
and
71 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
use proc_macro2::{Span, TokenStream}; | ||
use quote::{quote, ToTokens}; | ||
use syn::meta::ParseNestedMeta; | ||
use syn::{parse_quote, Error, ItemStatic, LitInt, LitStr, Meta, StaticMutability, Type}; | ||
|
||
const OPT_SECTION: &str = "section"; | ||
const OPT_NAME: &str = "name"; | ||
const OPT_TY: &str = "ty"; | ||
|
||
pub fn transform_note(opts: Options, mut item: ItemStatic) -> syn::Result<TokenStream> { | ||
// Forbid "used" and "link_section" attribute. | ||
fn unsupported_attr(attr: impl ToTokens) -> syn::Result<TokenStream> { | ||
Err(Error::new_spanned(attr, "unsupported attribute")) | ||
} | ||
|
||
for attr in &item.attrs { | ||
match &attr.meta { | ||
Meta::Path(p) => { | ||
if p.is_ident("used") { | ||
return unsupported_attr(p); | ||
} | ||
} | ||
Meta::List(_) => {} | ||
Meta::NameValue(a) => { | ||
if a.path.is_ident("link_section") { | ||
return unsupported_attr(&a.path); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Disallow mutable. | ||
if let StaticMutability::Mut(t) = &item.mutability { | ||
return Err(Error::new_spanned(t, "mutable note is not supported")); | ||
} | ||
|
||
// Get section name. | ||
let section = match opts.section { | ||
Some(v) => v, | ||
None => { | ||
return Err(Error::new( | ||
Span::call_site(), | ||
format_args!("missing `{OPT_SECTION}` option"), | ||
)); | ||
} | ||
}; | ||
|
||
// Get namespace. | ||
let mut name = match opts.name { | ||
Some(raw) => { | ||
let val = raw.value(); | ||
|
||
if val.contains('\0') { | ||
return Err(Error::new_spanned( | ||
raw, | ||
"note name cannot contains NUL character", | ||
)); | ||
} | ||
|
||
val | ||
} | ||
None => { | ||
return Err(Error::new( | ||
Span::call_site(), | ||
format_args!("missing `{OPT_NAME}` option"), | ||
)); | ||
} | ||
}; | ||
|
||
name.push('\0'); | ||
|
||
// Get type | ||
let ty: u32 = match opts.ty { | ||
Some(v) => v.base10_parse()?, | ||
None => { | ||
return Err(Error::new( | ||
Span::call_site(), | ||
format_args!("missing `{OPT_TY}` option"), | ||
)); | ||
} | ||
}; | ||
|
||
// Replace type. | ||
let nlen = name.len(); | ||
let dlen = match item.ty.as_ref() { | ||
Type::Array(arr) => match arr.elem.as_ref() { | ||
Type::Path(elem) if elem.qself.is_none() && elem.path.is_ident("u8") => &arr.len, | ||
t => return Err(Error::new_spanned(t, "expect `u8`")), | ||
}, | ||
t => return Err(Error::new_spanned(t, "expect array of `u8`")), | ||
}; | ||
|
||
item.ty = parse_quote!(crate::imgfmt::elf::Note<#nlen, { #dlen }>); | ||
|
||
// Replace value. | ||
let name = name.as_bytes(); | ||
let desc = item.expr; | ||
|
||
item.expr = parse_quote!(unsafe { crate::imgfmt::elf::Note::new([#(#name),*], #ty, #desc) }); | ||
|
||
// Compose. | ||
Ok(quote! { | ||
#[cfg(not(test))] | ||
#[used] | ||
#[link_section = #section] | ||
#item | ||
}) | ||
} | ||
|
||
#[derive(Default)] | ||
pub struct Options { | ||
section: Option<LitStr>, | ||
name: Option<LitStr>, | ||
ty: Option<LitInt>, | ||
} | ||
|
||
impl Options { | ||
pub fn parse(&mut self, m: ParseNestedMeta) -> syn::Result<()> { | ||
if m.path.is_ident(OPT_SECTION) { | ||
self.section = Some(m.value()?.parse()?); | ||
} else if m.path.is_ident(OPT_NAME) { | ||
self.name = Some(m.value()?.parse()?); | ||
} else if m.path.is_ident(OPT_TY) { | ||
self.ty = Some(m.value()?.parse()?); | ||
} else { | ||
return Err(m.error("unknown option")); | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub const PAGE_SIZE: usize = 0x1000; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub const PAGE_SIZE: usize = 0x1000; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
use core::ops::Deref; | ||
|
||
/// Single ELF note. | ||
#[repr(C)] | ||
pub struct Note<const N: usize, const D: usize> { | ||
hdr: NoteHdr, | ||
name: [u8; N], | ||
desc: NoteDesc<D>, | ||
} | ||
|
||
impl<const N: usize, const D: usize> Note<N, D> { | ||
/// # Safety | ||
/// `name` must contains NUL as a last element. | ||
pub const unsafe fn new(name: [u8; N], ty: u32, desc: [u8; D]) -> Self { | ||
Self { | ||
hdr: NoteHdr { | ||
name_len: N as _, | ||
desc_len: D as _, | ||
ty, | ||
}, | ||
name, | ||
desc: NoteDesc(desc), | ||
} | ||
} | ||
} | ||
|
||
/// Implementation of `Elf64_Nhdr` and `Elf32_Nhdr` structure. | ||
#[repr(C)] | ||
pub struct NoteHdr { | ||
/// n_namesz. | ||
pub name_len: u32, | ||
/// n_descsz. | ||
pub desc_len: u32, | ||
/// n_type. | ||
pub ty: u32, | ||
} | ||
|
||
/// Note description. | ||
#[repr(C, align(4))] | ||
pub struct NoteDesc<const L: usize>([u8; L]); | ||
|
||
impl<const L: usize> Deref for NoteDesc<L> { | ||
type Target = [u8; L]; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.0 | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use core::mem::offset_of; | ||
|
||
#[test] | ||
fn note() { | ||
assert_eq!(offset_of!(Note::<3, 1>, name), 12); | ||
assert_eq!(offset_of!(Note::<3, 1>, desc), 16); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod elf; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ use obconf::BootEnv; | |
|
||
mod config; | ||
mod console; | ||
mod imgfmt; | ||
|
||
/// Entry point of the kernel. | ||
/// | ||
|