Skip to main content

linker_utils/
utils.rs

1use anyhow::Result;
2use anyhow::ensure;
3use std::ffi::CStr;
4
5// Return u32 from a byte slice
6#[must_use]
7pub fn u32_from_slice(data: &[u8]) -> u32 {
8    u32::from_le_bytes(*data.first_chunk::<4>().unwrap())
9}
10
11// Return u64 from a byte slice
12#[must_use]
13pub fn u64_from_slice(data: &[u8]) -> u64 {
14    u64::from_le_bytes(*data.first_chunk::<8>().unwrap())
15}
16
17// Copy `mask` slice into the `dest` slice using OR operation.
18pub fn or_from_slice(dest: &mut [u8], mask_bytes: &[u8]) {
19    for (i, v) in mask_bytes.iter().enumerate() {
20        dest[i] |= *v;
21    }
22}
23
24// And `mask` slice with the `dest` slice using AND operation.
25pub fn and_from_slice(dest: &mut [u8], mask_bytes: &[u8]) {
26    for (i, v) in mask_bytes.iter().enumerate() {
27        dest[i] &= *v;
28    }
29}
30
31// Interpret all bytes in `data` as a slice of `T`.
32#[must_use]
33pub fn slice_from_all_bytes<T: object::Pod>(data: &[u8]) -> &[T] {
34    object::slice_from_bytes(data, data.len() / size_of::<T>())
35        .unwrap()
36        .0
37}
38
39#[must_use]
40pub fn slice_from_all_bytes_mut<T: object::Pod>(data: &mut [u8]) -> &mut [T] {
41    object::slice_from_bytes_mut(data, data.len() / size_of::<T>())
42        .unwrap()
43        .0
44}
45
46pub fn read_u32(content: &mut &[u8]) -> Result<u32> {
47    ensure!(content.len() >= 4, "Not enough bytes to read u32");
48    let value = u32::from_le_bytes(content[..4].try_into()?);
49    *content = &content[4..];
50    Ok(value)
51}
52
53pub fn read_string(content: &mut &[u8]) -> Result<String> {
54    let cstr = CStr::from_bytes_until_nul(content)
55        .map_err(|_| anyhow::anyhow!("No null terminator found in string"))?;
56    let len = cstr.count_bytes() + 1; // include the null terminator
57    let s = cstr.to_string_lossy().to_string();
58    *content = &content[len..];
59    Ok(s)
60}
61
62pub fn read_uleb128(content: &mut &[u8]) -> Result<u64> {
63    leb128::read::unsigned(content)
64        .map_err(|e| anyhow::anyhow!("Failed to read ULEB128 value: {e}"))
65}