Struct mod_mgmt::CrateNamespace
source · pub struct CrateNamespace { /* private fields */ }
Expand description
This struct represents a namespace of crates and their “global” (publicly-visible) symbols. A crate namespace struct is basically a container around many crates that have all been loaded and linked against each other, completely separate and in isolation from any other crate namespace (although a given crate may be shared across multiple namespaces).
Each CrateNamespace
can be treated as a separate OS personality,
but are significantly more efficient than library OS-style personalities.
A CrateNamespace
is also useful to create a process (task group) abstraction.
CrateNamespace
s can also optionally be recursive.
For example, a namespace that holds just application crates and symbols
can recursively rely upon (link against) the crates and symbols in a lower-level namespace
that contains kernel crates and symbols.
Implementations§
source§impl CrateNamespace
impl CrateNamespace
sourcepub fn new(
name: String,
dir: NamespaceDir,
recursive_namespace: Option<Arc<CrateNamespace>>
) -> CrateNamespace
pub fn new( name: String, dir: NamespaceDir, recursive_namespace: Option<Arc<CrateNamespace>> ) -> CrateNamespace
Creates a new CrateNamespace
that is completely empty (no loaded crates).
Arguments
name
: the name of thisCrateNamespace
, used only for convenience purposes.dir
: the directory of crate object files for this namespace.recursive_namespace
: anotherCrateNamespace
that can optionally be used to recursively resolve missing crates/symbols.
sourcepub fn name(&self) -> &str
pub fn name(&self) -> &str
Returns the name of this CrateNamespace
, which is just used for debugging purposes.
sourcepub fn dir(&self) -> &NamespaceDir
pub fn dir(&self) -> &NamespaceDir
Returns the directory that this CrateNamespace
is based on.
sourcepub fn recursive_namespace(&self) -> Option<&Arc<CrateNamespace>>
pub fn recursive_namespace(&self) -> Option<&Arc<CrateNamespace>>
Returns the recursive namespace that this CrateNamespace
is built atop,
if one exists.
sourcepub fn get_tls_initializer_data(&self) -> TlsDataImage
pub fn get_tls_initializer_data(&self) -> TlsDataImage
Returns a new copy of this namespace’s initial TLS area, which can be used as the initial TLS area data image for a new task.
sourcepub fn crate_names(&self, recursive: bool) -> Vec<StrRef>
pub fn crate_names(&self, recursive: bool) -> Vec<StrRef>
Returns a list of all of the crate names currently loaded into this CrateNamespace
,
including all crates in any recursive namespaces as well if recursive
is true
.
This is a slow method mostly for debugging, since it allocates a new vector of crate names.
sourcepub fn for_each_crate<F>(&self, recursive: bool, f: F)where
F: FnMut(&str, &StrongCrateRef) -> bool,
pub fn for_each_crate<F>(&self, recursive: bool, f: F)where F: FnMut(&str, &StrongCrateRef) -> bool,
Iterates over all crates in this namespace and calls the given function f
on each crate.
If recursive
is true, crates in recursive namespaces are included in the iteration as well.
The function f
is called with two arguments: the name of the crate, and a reference to the crate.
The function f
must return a boolean value that indicates whether to continue iterating;
if true
, the iteration will continue, if false
, the iteration will stop.
sourcepub fn get_crate(&self, crate_name: &str) -> Option<StrongCrateRef>
pub fn get_crate(&self, crate_name: &str) -> Option<StrongCrateRef>
Acquires the lock on this CrateNamespace
’s crate list and returns the crate
that matches the given crate_name
, if it exists in this namespace.
If it does not exist in this namespace, then the recursive namespace is searched as well.
Important note about Return value
Returns a StrongCrateReference
that has not been marked as a shared crate reference,
so if the caller wants to keep the returned StrongCrateRef
as a shared crate
that jointly exists in another namespace, they should invoke the
CowArc::clone()
function on the returned value.
sourcepub fn get_crate_and_namespace<'n>(
namespace: &'n Arc<CrateNamespace>,
crate_name: &str
) -> Option<(StrongCrateRef, &'n Arc<CrateNamespace>)>
pub fn get_crate_and_namespace<'n>( namespace: &'n Arc<CrateNamespace>, crate_name: &str ) -> Option<(StrongCrateRef, &'n Arc<CrateNamespace>)>
Acquires the lock on this CrateNamespace
’s crate list and returns the crate
that matches the given crate_name
, if it exists in this namespace.
If it does not exist in this namespace, then the recursive namespace is searched as well.
This function is similar to the get_crate
method,
but it also returns the CrateNamespace
in which the crate was found.
It is an associated function rather than a method so it can operate on Arc<CrateNamespace>
s.
Important note about Return value
Returns a StrongCrateReference
that has not been marked as a shared crate reference,
so if the caller wants to keep the returned StrongCrateRef
as a shared crate
that jointly exists in another namespace, they should invoke the
CowArc::clone()
function on the returned value.
sourcepub fn get_crates_starting_with<'n>(
namespace: &'n Arc<CrateNamespace>,
crate_name_prefix: &str
) -> Vec<(StrRef, StrongCrateRef, &'n Arc<CrateNamespace>)>
pub fn get_crates_starting_with<'n>( namespace: &'n Arc<CrateNamespace>, crate_name_prefix: &str ) -> Vec<(StrRef, StrongCrateRef, &'n Arc<CrateNamespace>)>
Finds the LoadedCrate
s whose names start with the given crate_name_prefix
.
Return
Returns a list of matching crates, in the form of a tuple containing the crate’s name,
a shallow-cloned reference to the crate, and a reference to the namespace in which the matching crate was found.
If you want to add the returned crate to another namespace,
you MUST fully clone()
the returned crate reference in order to mark that crate as shared across namespaces.
Important Usage Note
To avoid greedily matching more crates than expected, you may wish to end the crate_name_prefix
with “-
”.
This may provide results more in line with the caller’s expectations; see the last example below about a trailing “-
”.
This works because the delimiter between a crate name and its trailing hash value is “-
”.
Example
- This
CrateNamespace
contains the cratesmy_crate-843a613894da0c24
andmy_crate_new-933a635894ce0f12
. Callingget_crates_starting_with("my_crate")
will return both crates,
sourcepub fn get_crate_starting_with<'n>(
namespace: &'n Arc<CrateNamespace>,
crate_name_prefix: &str
) -> Option<(StrRef, StrongCrateRef, &'n Arc<CrateNamespace>)>
pub fn get_crate_starting_with<'n>( namespace: &'n Arc<CrateNamespace>, crate_name_prefix: &str ) -> Option<(StrRef, StrongCrateRef, &'n Arc<CrateNamespace>)>
Finds the LoadedCrate
whose name starts with the given crate_name_prefix
,
if and only if there is a single matching crate in this namespace or any of its recursive namespaces.
This is a convenience wrapper around the get_crates_starting_with()
method.
Return
Returns a tuple containing the crate’s name, a shallow-cloned reference to the crate,
and a reference to the namespace in which the matching crate was found.
If you want to add the returned crate to another namespace,
you MUST fully clone()
the returned crate reference in order to mark that crate as shared across namespaces.
Important Usage Note
To avoid greedily matching more crates than expected, you may wish to end the crate_name_prefix
with “-
”.
This may provide results more in line with the caller’s expectations; see the last example below about a trailing “-
”.
This works because the delimiter between a crate name and its trailing hash value is “-
”.
Example
- This
CrateNamespace
contains the cratesmy_crate-843a613894da0c24
andmy_crate_new-933a635894ce0f12
. Callingget_crate_starting_with("my_crate")
will return None, because it will match bothmy_crate
andmy_crate_new
. To match onlymy_crate
, call this function asget_crate_starting_with("my_crate-")
.
sourcepub fn get_crate_object_files_starting_with<'n>(
namespace: &'n Arc<CrateNamespace>,
file_name_prefix: &str
) -> Vec<(FileRef, &'n Arc<CrateNamespace>)>
pub fn get_crate_object_files_starting_with<'n>( namespace: &'n Arc<CrateNamespace>, file_name_prefix: &str ) -> Vec<(FileRef, &'n Arc<CrateNamespace>)>
Like get_crates_starting_with()
,
but for crate object files instead of loaded crates.
Returns a list of matching object files and the namespace in which they were found, inclusive of recursive namespaces.
sourcepub fn get_crate_object_file_starting_with<'n>(
namespace: &'n Arc<CrateNamespace>,
file_name_prefix: &str
) -> Option<(FileRef, &'n Arc<CrateNamespace>)>
pub fn get_crate_object_file_starting_with<'n>( namespace: &'n Arc<CrateNamespace>, file_name_prefix: &str ) -> Option<(FileRef, &'n Arc<CrateNamespace>)>
Like get_crate_starting_with()
,
but for crate object files instead of loaded crates.
Returns the matching object file and the namespace in which it was found, if and only if there was a single match (inclusive of recursive namespaces).
sourcepub fn method_get_crate_object_files_starting_with(
&self,
file_name_prefix: &str
) -> Vec<(FileRef, &CrateNamespace)>
pub fn method_get_crate_object_files_starting_with( &self, file_name_prefix: &str ) -> Vec<(FileRef, &CrateNamespace)>
Same as get_crate_object_files_starting_with()
,
but is a method instead of an associated function,
and also returns &CrateNamespace
instead of &Arc<CrateNamespace>
.
This is only necessary because I can’t figure out how to make a generic function
that accepts and returns either &CrateNamespace
or &Arc<CrateNamespace>
.
sourcepub fn method_get_crate_object_file_starting_with(
&self,
file_name_prefix: &str
) -> Option<(FileRef, &CrateNamespace)>
pub fn method_get_crate_object_file_starting_with( &self, file_name_prefix: &str ) -> Option<(FileRef, &CrateNamespace)>
Same as get_crate_object_file_starting_with()
,
but is a method instead of an associated function,
and also returns &CrateNamespace
instead of &Arc<CrateNamespace>
.
This is only necessary because I can’t figure out how to make a generic function
that accepts and returns either &CrateNamespace
or &Arc<CrateNamespace>
.
sourcepub fn load_crate_as_application(
namespace: &Arc<CrateNamespace>,
crate_object_file: &FileRef,
kernel_mmi_ref: &MmiRef,
verbose_log: bool
) -> Result<AppCrateRef, &'static str>
pub fn load_crate_as_application( namespace: &Arc<CrateNamespace>, crate_object_file: &FileRef, kernel_mmi_ref: &MmiRef, verbose_log: bool ) -> Result<AppCrateRef, &'static str>
Loads the specified application crate into this CrateNamespace
, allowing it to be run.
The new application crate’s public symbols are added to this CrateNamespace
’s symbol map,
allowing other crates in this namespace to depend upon it.
Application crates are added to the CrateNamespace just like kernel crates, so to load an application crate multiple times to spawn multiple instances of it, you can create a new top-level namespace to hold that application crate.
Returns a Result containing the newly-loaded application crate itself.
sourcepub fn load_crate(
&self,
crate_object_file: &FileRef,
temp_backup_namespace: Option<&CrateNamespace>,
kernel_mmi_ref: &MmiRef,
verbose_log: bool
) -> Result<(StrongCrateRef, usize), &'static str>
pub fn load_crate( &self, crate_object_file: &FileRef, temp_backup_namespace: Option<&CrateNamespace>, kernel_mmi_ref: &MmiRef, verbose_log: bool ) -> Result<(StrongCrateRef, usize), &'static str>
Loads the specified crate into memory, allowing it to be invoked.
Returns a Result containing the number of symbols that were added to the symbol map
as a result of loading this crate.
Arguments
crate_object_file
: the crate object file that will be loaded into thisCrateNamespace
.temp_backup_namespace
: theCrateNamespace
that should be searched for missing symbols (for relocations) if a symbol cannot be found in thisCrateNamespace
. Iftemp_backup_namespace
isNone
, then no other namespace will be searched, and any missing symbols will return anErr
.kernel_mmi_ref
: a mutable reference to the kernel’sMemoryManagementInfo
.verbose_log
: a boolean value whether to enable verbose_log logging of crate loading actions.
sourcepub fn load_crates<'f, I>(
&self,
crate_files: I,
temp_backup_namespace: Option<&CrateNamespace>,
kernel_mmi_ref: &MmiRef,
verbose_log: bool
) -> Result<(), &'static str>where
I: Iterator<Item = &'f FileRef>,
pub fn load_crates<'f, I>( &self, crate_files: I, temp_backup_namespace: Option<&CrateNamespace>, kernel_mmi_ref: &MmiRef, verbose_log: bool ) -> Result<(), &'static str>where I: Iterator<Item = &'f FileRef>,
This function first loads all of the given crates’ sections and adds them to the symbol map, and only after all crates are loaded does it move on to linking/relocation calculations.
This allows multiple object files with circular dependencies on one another to be loaded all at once, as if they were a single entity.
Example
If crate A
depends on crate B
, and crate B
depends on crate A
,
this function will load both crate A
and B
before trying to resolve their dependencies individually.
sourcepub fn clone_on_write(&self) -> CrateNamespace
pub fn clone_on_write(&self) -> CrateNamespace
Duplicates this CrateNamespace
into a new CrateNamespace
,
but uses a copy-on-write/clone-on-write semantic that creates
a special shared reference to each crate that indicates it is shared across multiple namespaces.
In other words, crates in the new namespace returned by this fucntions are fully shared with crates in this namespace, until either namespace attempts to modify a shared crate in the future.
When modifying crates in the new namespace, e.g., swapping crates,
any crates in the new namespace that are still shared with the old namespace
must be deeply copied into a new crate that is exclusively owned,
and then that new crate will be modified in whichever way desired.
For example, if you swapped one crate A
in the new namespace returned from this function
and loaded a new crate A2
in its place,
and two other crates B
and C
depended on that newly swapped-out A
,
then B
and C
would be transparently deep copied before modifying them to depend on
the new crate A2
, and you would be left with B2
and C2
as deep copies of B
and C
,
that now depend on A2
instead of A
.
The existing versions of B
and C
would still depend on A
,
but they would no longer be part of the new namespace.
sourcepub fn rewrite_section_dependents(
old_section: &StrongSectionRef,
new_section: &StrongSectionRef,
kernel_mmi_ref: &MmiRef
) -> Result<(), &'static str>
pub fn rewrite_section_dependents( old_section: &StrongSectionRef, new_section: &StrongSectionRef, kernel_mmi_ref: &MmiRef ) -> Result<(), &'static str>
Finds all of the weak dependents (sections that depend on the given old_section
)
and rewrites their relocation entries to point to the given new_section
.
This effectively replaces the usage of the old_section
with the new_section
,
but does not make any modifications to symbol maps.
sourcepub fn add_symbols<'a, I>(&self, sections: I, _log_replacements: bool) -> usizewhere
I: IntoIterator<Item = &'a StrongSectionRef>,
pub fn add_symbols<'a, I>(&self, sections: I, _log_replacements: bool) -> usizewhere I: IntoIterator<Item = &'a StrongSectionRef>,
Adds only global symbols in the given sections
iterator to this namespace’s symbol map,
If a symbol already exists in the symbol map, this replaces the existing symbol but does not count it as a newly-added one.
Returns the number of new unique symbols added.
sourcepub fn get_crate_containing_address(
&self,
virt_addr: VirtualAddress,
search_all_section_types: bool
) -> Option<StrongCrateRef>
pub fn get_crate_containing_address( &self, virt_addr: VirtualAddress, search_all_section_types: bool ) -> Option<StrongCrateRef>
Finds the crate that contains the given VirtualAddress
in its loaded code.
By default, only executable sections (.text
) are searched, since typically the only use case
for this function is to search for an instruction pointer (program counter) address.
However, if search_all_section_types
is true
, both the read-only and read-write sections
will be included in the search, e.g., .rodata
, .data
, .bss
.
Usage
This is mostly useful for printing symbol names for a stack trace (backtrace).
It is also similar in functionality to the tool addr2line
,
but gives the section itself rather than the line of code.
Locking
This can obtain the lock on every crate and every section,
so to avoid deadlock, please ensure that the caller task does not hold any such locks.
It does not need to obtain locks on the underlying MappedPages
regions.
Note
This is a slow procedure because, in the worst case, it will iterate through every loaded crate in this namespace (and its recursive namespace).
sourcepub fn get_section_containing_address(
&self,
virt_addr: VirtualAddress,
search_all_section_types: bool
) -> Option<(StrongSectionRef, usize)>
pub fn get_section_containing_address( &self, virt_addr: VirtualAddress, search_all_section_types: bool ) -> Option<(StrongSectionRef, usize)>
Finds the section that contains the given VirtualAddress
in its loaded code.
By default, only executable sections (.text
) are searched, since the typical use case
for this function is to search for an instruction pointer (program counter) address.
However, if search_all_section_types
is true
, both the read-only and read-write sections
will be included in the search, e.g., .rodata
, .data
, .bss
.
Usage
This is mostly useful for printing symbol names for a stack trace (backtrace).
It is also similar in functionality to the tool addr2line
,
but gives the section itself rather than the line of code.
Locking
This can obtain the lock on every crate in this namespace and its recursive namespaces, so to avoid deadlock, please ensure that the caller task does not hold any such locks.
Note
This is a slow procedure because, in the worst case, it will iterate through every section in every loaded crate in this namespace (and its recursive namespace), not just the publicly-visible (global) sections.
sourcepub fn get_symbol_and_namespace(
&self,
demangled_full_symbol: &str
) -> Option<(WeakSectionRef, &CrateNamespace)>
pub fn get_symbol_and_namespace( &self, demangled_full_symbol: &str ) -> Option<(WeakSectionRef, &CrateNamespace)>
Like get_symbol()
, but also returns the exact CrateNamespace
where the symbol was found.
sourcepub fn get_symbol(&self, demangled_full_symbol: &str) -> WeakSectionRef
pub fn get_symbol(&self, demangled_full_symbol: &str) -> WeakSectionRef
Finds the corresponding LoadedSection
reference for the given fully-qualified symbol string.
Searches this namespace first, and then its recursive namespace as well.
sourcepub fn get_symbol_or_load(
&self,
demangled_full_symbol: &str,
temp_backup_namespace: Option<&CrateNamespace>,
kernel_mmi_ref: &MmiRef,
verbose_log: bool
) -> WeakSectionRef
pub fn get_symbol_or_load( &self, demangled_full_symbol: &str, temp_backup_namespace: Option<&CrateNamespace>, kernel_mmi_ref: &MmiRef, verbose_log: bool ) -> WeakSectionRef
Finds the corresponding LoadedSection
reference for the given fully-qualified symbol string,
similar to the simpler function get_symbol()
, but takes the additional step of trying to
automatically find and/or load the crate containing that symbol
(and does so recursively for any of its crate dependencies).
(1) First, it recursively searches this namespace’s and its recursive namespaces’ symbol maps, and returns the symbol if already loaded.
(2) Second, if the symbol is missing from this namespace, it looks in the temp_backup_namespace
.
If we find it there, then we add that symbol and its containing crate as a shared crate in this namespace.
(3) Third, if this namespace has fuzzy_symbol_matching
enabled, it searches the backup namespace
for symbols that match the given demangled_full_symbol
without the hash suffix.
(4) Fourth, if the missing symbol isn’t in the backup namespace either,
try to load its containing crate from the object file.
This can only be done for symbols that have a leading crate name, such as “my_crate::foo”;
if a symbol was given the no_mangle
attribute, then we will not be able to find it,
and that symbol’s containing crate should be manually loaded before invoking this.
Arguments
demangled_full_symbol
: a fully-qualified symbol string, e.g., “my_crate::MyStruct::foo::h843a9ea794da0c24”.temp_backup_namespace
: theCrateNamespace
that should be temporarily searched (just during this call) for the missing symbol. Iftemp_backup_namespace
isNone
, then only this namespace (and its recursive namespaces) will be searched.kernel_mmi_ref
: a reference to the kernel’sMemoryManagementInfo
, which must not be locked.
sourcepub fn find_symbols_starting_with(
&self,
symbol_prefix: &str
) -> Vec<(String, WeakSectionRef)>
pub fn find_symbols_starting_with( &self, symbol_prefix: &str ) -> Vec<(String, WeakSectionRef)>
Returns a copied list of the corresponding LoadedSection
s
with names that start with the given symbol_prefix
.
This will also search the recursive namespace’s symbol map.
This method causes allocation because it creates a copy of the matching entries in the symbol map.
Example
The symbol map contains my_crate::foo::h843a613894da0c24
and
my_crate::foo::h933a635894ce0f12
.
Calling find_symbols_starting_with("my_crate::foo")
will return
a vector containing both sections, which can then be iterated through.
sourcepub fn find_symbols_starting_with_and_namespace(
&self,
symbol_prefix: &str
) -> Vec<(String, WeakSectionRef, &CrateNamespace)>
pub fn find_symbols_starting_with_and_namespace( &self, symbol_prefix: &str ) -> Vec<(String, WeakSectionRef, &CrateNamespace)>
Similar to find_symbols_starting_with
, but also includes a reference to the exact CrateNamespace
where the matching symbol was found.
sourcepub fn get_symbol_starting_with(&self, symbol_prefix: &str) -> WeakSectionRef
pub fn get_symbol_starting_with(&self, symbol_prefix: &str) -> WeakSectionRef
Returns a weak reference to the LoadedSection
whose name beings with the given symbol_prefix
,
if and only if the symbol map only contains a single possible matching symbol.
This will also search the recursive namespace’s symbol map.
Important Usage Note
To avoid greedily matching more symbols than expected, you may wish to end the symbol_prefix
with “::
”.
This may provide results more in line with the caller’s expectations; see the last example below about a trailing “::
”.
This works because the delimiter between a symbol and its trailing hash value is “::
”.
Example
- The symbol map contains
my_crate::foo::h843a613894da0c24
and no other symbols that start withmy_crate::foo
. Callingget_symbol_starting_with("my_crate::foo")
will return a weak reference to the sectionmy_crate::foo::h843a613894da0c24
. - The symbol map contains
my_crate::foo::h843a613894da0c24
andmy_crate::foo::h933a635894ce0f12
. Callingget_symbol_starting_with("my_crate::foo")
will return an empty (default) weak reference, which is the same as returing None. - (Important) The symbol map contains
my_crate::foo::h843a613894da0c24
andmy_crate::foo_new::h933a635894ce0f12
. Callingget_symbol_starting_with("my_crate::foo")
will return an empty (default) weak reference, which is the same as returing None, because it will match bothfoo
andfoo_new
. To match onlyfoo
, call this function asget_symbol_starting_with("my_crate::foo::")
(note the trailing “::
”).
sourcepub fn dump_symbol_map(&self) -> String
pub fn dump_symbol_map(&self) -> String
Simple debugging function that returns the entire symbol map as a String. This includes only symbols from this namespace, and excludes symbols from recursive namespaces.
sourcepub fn dump_symbol_map_recursive(&self) -> String
pub fn dump_symbol_map_recursive(&self) -> String
Same as dump_symbol_map()
,
but includes symbols from recursive namespaces.