xref: /linux/rust/macros/module.rs (revision 2fd001cd36005846caa6456fff1008c6f5bae9d4)
1  // SPDX-License-Identifier: GPL-2.0
2  
3  use crate::helpers::*;
4  use proc_macro::{token_stream, Delimiter, Literal, TokenStream, TokenTree};
5  use std::fmt::Write;
6  
7  fn expect_string_array(it: &mut token_stream::IntoIter) -> Vec<String> {
8      let group = expect_group(it);
9      assert_eq!(group.delimiter(), Delimiter::Bracket);
10      let mut values = Vec::new();
11      let mut it = group.stream().into_iter();
12  
13      while let Some(val) = try_string(&mut it) {
14          assert!(val.is_ascii(), "Expected ASCII string");
15          values.push(val);
16          match it.next() {
17              Some(TokenTree::Punct(punct)) => assert_eq!(punct.as_char(), ','),
18              None => break,
19              _ => panic!("Expected ',' or end of array"),
20          }
21      }
22      values
23  }
24  
25  struct ModInfoBuilder<'a> {
26      module: &'a str,
27      counter: usize,
28      buffer: String,
29  }
30  
31  impl<'a> ModInfoBuilder<'a> {
32      fn new(module: &'a str) -> Self {
33          ModInfoBuilder {
34              module,
35              counter: 0,
36              buffer: String::new(),
37          }
38      }
39  
40      fn emit_base(&mut self, field: &str, content: &str, builtin: bool) {
41          let string = if builtin {
42              // Built-in modules prefix their modinfo strings by `module.`.
43              format!(
44                  "{module}.{field}={content}\0",
45                  module = self.module,
46                  field = field,
47                  content = content
48              )
49          } else {
50              // Loadable modules' modinfo strings go as-is.
51              format!("{field}={content}\0", field = field, content = content)
52          };
53  
54          write!(
55              &mut self.buffer,
56              "
57                  {cfg}
58                  #[doc(hidden)]
59                  #[link_section = \".modinfo\"]
60                  #[used]
61                  pub static __{module}_{counter}: [u8; {length}] = *{string};
62              ",
63              cfg = if builtin {
64                  "#[cfg(not(MODULE))]"
65              } else {
66                  "#[cfg(MODULE)]"
67              },
68              module = self.module.to_uppercase(),
69              counter = self.counter,
70              length = string.len(),
71              string = Literal::byte_string(string.as_bytes()),
72          )
73          .unwrap();
74  
75          self.counter += 1;
76      }
77  
78      fn emit_only_builtin(&mut self, field: &str, content: &str) {
79          self.emit_base(field, content, true)
80      }
81  
82      fn emit_only_loadable(&mut self, field: &str, content: &str) {
83          self.emit_base(field, content, false)
84      }
85  
86      fn emit(&mut self, field: &str, content: &str) {
87          self.emit_only_builtin(field, content);
88          self.emit_only_loadable(field, content);
89      }
90  }
91  
92  #[derive(Debug, Default)]
93  struct ModuleInfo {
94      type_: String,
95      license: String,
96      name: String,
97      author: Option<String>,
98      description: Option<String>,
99      alias: Option<Vec<String>>,
100  }
101  
102  impl ModuleInfo {
103      fn parse(it: &mut token_stream::IntoIter) -> Self {
104          let mut info = ModuleInfo::default();
105  
106          const EXPECTED_KEYS: &[&str] =
107              &["type", "name", "author", "description", "license", "alias"];
108          const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
109          let mut seen_keys = Vec::new();
110  
111          loop {
112              let key = match it.next() {
113                  Some(TokenTree::Ident(ident)) => ident.to_string(),
114                  Some(_) => panic!("Expected Ident or end"),
115                  None => break,
116              };
117  
118              if seen_keys.contains(&key) {
119                  panic!(
120                      "Duplicated key \"{}\". Keys can only be specified once.",
121                      key
122                  );
123              }
124  
125              assert_eq!(expect_punct(it), ':');
126  
127              match key.as_str() {
128                  "type" => info.type_ = expect_ident(it),
129                  "name" => info.name = expect_string_ascii(it),
130                  "author" => info.author = Some(expect_string(it)),
131                  "description" => info.description = Some(expect_string(it)),
132                  "license" => info.license = expect_string_ascii(it),
133                  "alias" => info.alias = Some(expect_string_array(it)),
134                  _ => panic!(
135                      "Unknown key \"{}\". Valid keys are: {:?}.",
136                      key, EXPECTED_KEYS
137                  ),
138              }
139  
140              assert_eq!(expect_punct(it), ',');
141  
142              seen_keys.push(key);
143          }
144  
145          expect_end(it);
146  
147          for key in REQUIRED_KEYS {
148              if !seen_keys.iter().any(|e| e == key) {
149                  panic!("Missing required key \"{}\".", key);
150              }
151          }
152  
153          let mut ordered_keys: Vec<&str> = Vec::new();
154          for key in EXPECTED_KEYS {
155              if seen_keys.iter().any(|e| e == key) {
156                  ordered_keys.push(key);
157              }
158          }
159  
160          if seen_keys != ordered_keys {
161              panic!(
162                  "Keys are not ordered as expected. Order them like: {:?}.",
163                  ordered_keys
164              );
165          }
166  
167          info
168      }
169  }
170  
171  pub(crate) fn module(ts: TokenStream) -> TokenStream {
172      let mut it = ts.into_iter();
173  
174      let info = ModuleInfo::parse(&mut it);
175  
176      let mut modinfo = ModInfoBuilder::new(info.name.as_ref());
177      if let Some(author) = info.author {
178          modinfo.emit("author", &author);
179      }
180      if let Some(description) = info.description {
181          modinfo.emit("description", &description);
182      }
183      modinfo.emit("license", &info.license);
184      if let Some(aliases) = info.alias {
185          for alias in aliases {
186              modinfo.emit("alias", &alias);
187          }
188      }
189  
190      // Built-in modules also export the `file` modinfo string.
191      let file =
192          std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable");
193      modinfo.emit_only_builtin("file", &file);
194  
195      format!(
196          "
197              /// The module name.
198              ///
199              /// Used by the printing macros, e.g. [`info!`].
200              const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
201  
202              // SAFETY: `__this_module` is constructed by the kernel at load time and will not be
203              // freed until the module is unloaded.
204              #[cfg(MODULE)]
205              static THIS_MODULE: kernel::ThisModule = unsafe {{
206                  kernel::ThisModule::from_ptr(&kernel::bindings::__this_module as *const _ as *mut _)
207              }};
208              #[cfg(not(MODULE))]
209              static THIS_MODULE: kernel::ThisModule = unsafe {{
210                  kernel::ThisModule::from_ptr(core::ptr::null_mut())
211              }};
212  
213              // Double nested modules, since then nobody can access the public items inside.
214              mod __module_init {{
215                  mod __module_init {{
216                      use super::super::{type_};
217  
218                      /// The \"Rust loadable module\" mark.
219                      //
220                      // This may be best done another way later on, e.g. as a new modinfo
221                      // key or a new section. For the moment, keep it simple.
222                      #[cfg(MODULE)]
223                      #[doc(hidden)]
224                      #[used]
225                      static __IS_RUST_MODULE: () = ();
226  
227                      static mut __MOD: Option<{type_}> = None;
228  
229                      // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
230                      /// # Safety
231                      ///
232                      /// This function must not be called after module initialization, because it may be
233                      /// freed after that completes.
234                      #[cfg(MODULE)]
235                      #[doc(hidden)]
236                      #[no_mangle]
237                      #[link_section = \".init.text\"]
238                      pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{
239                          // SAFETY: This function is inaccessible to the outside due to the double
240                          // module wrapping it. It is called exactly once by the C side via its
241                          // unique name.
242                          unsafe {{ __init() }}
243                      }}
244  
245                      #[cfg(MODULE)]
246                      #[doc(hidden)]
247                      #[no_mangle]
248                      pub extern \"C\" fn cleanup_module() {{
249                          // SAFETY:
250                          // - This function is inaccessible to the outside due to the double
251                          //   module wrapping it. It is called exactly once by the C side via its
252                          //   unique name,
253                          // - furthermore it is only called after `init_module` has returned `0`
254                          //   (which delegates to `__init`).
255                          unsafe {{ __exit() }}
256                      }}
257  
258                      // Built-in modules are initialized through an initcall pointer
259                      // and the identifiers need to be unique.
260                      #[cfg(not(MODULE))]
261                      #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
262                      #[doc(hidden)]
263                      #[link_section = \"{initcall_section}\"]
264                      #[used]
265                      pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init;
266  
267                      #[cfg(not(MODULE))]
268                      #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
269                      core::arch::global_asm!(
270                          r#\".section \"{initcall_section}\", \"a\"
271                          __{name}_initcall:
272                              .long   __{name}_init - .
273                              .previous
274                          \"#
275                      );
276  
277                      #[cfg(not(MODULE))]
278                      #[doc(hidden)]
279                      #[no_mangle]
280                      pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
281                          // SAFETY: This function is inaccessible to the outside due to the double
282                          // module wrapping it. It is called exactly once by the C side via its
283                          // placement above in the initcall section.
284                          unsafe {{ __init() }}
285                      }}
286  
287                      #[cfg(not(MODULE))]
288                      #[doc(hidden)]
289                      #[no_mangle]
290                      pub extern \"C\" fn __{name}_exit() {{
291                          // SAFETY:
292                          // - This function is inaccessible to the outside due to the double
293                          //   module wrapping it. It is called exactly once by the C side via its
294                          //   unique name,
295                          // - furthermore it is only called after `__{name}_init` has returned `0`
296                          //   (which delegates to `__init`).
297                          unsafe {{ __exit() }}
298                      }}
299  
300                      /// # Safety
301                      ///
302                      /// This function must only be called once.
303                      unsafe fn __init() -> core::ffi::c_int {{
304                          match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{
305                              Ok(m) => {{
306                                  // SAFETY: No data race, since `__MOD` can only be accessed by this
307                                  // module and there only `__init` and `__exit` access it. These
308                                  // functions are only called once and `__exit` cannot be called
309                                  // before or during `__init`.
310                                  unsafe {{
311                                      __MOD = Some(m);
312                                  }}
313                                  return 0;
314                              }}
315                              Err(e) => {{
316                                  return e.to_errno();
317                              }}
318                          }}
319                      }}
320  
321                      /// # Safety
322                      ///
323                      /// This function must
324                      /// - only be called once,
325                      /// - be called after `__init` has been called and returned `0`.
326                      unsafe fn __exit() {{
327                          // SAFETY: No data race, since `__MOD` can only be accessed by this module
328                          // and there only `__init` and `__exit` access it. These functions are only
329                          // called once and `__init` was already called.
330                          unsafe {{
331                              // Invokes `drop()` on `__MOD`, which should be used for cleanup.
332                              __MOD = None;
333                          }}
334                      }}
335  
336                      {modinfo}
337                  }}
338              }}
339          ",
340          type_ = info.type_,
341          name = info.name,
342          modinfo = modinfo.buffer,
343          initcall_section = ".initcall6.init"
344      )
345      .parse()
346      .expect("Error parsing formatted string into token stream.")
347  }
348