Skip to content

Commit

Permalink
Store Cow inside ElfNSlice enum
Browse files Browse the repository at this point in the history
Similar to what we did for the ElfN enum, store a Cow object instead of
a reference inside ElfNSlice. Doing so will allow us to abstract over
the precise memory representation, which can change depending on the
backend in use.

Signed-off-by: Daniel Müller <[email protected]>
  • Loading branch information
d-e-s-o committed Dec 18, 2024
1 parent c7600e5 commit 306af62
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 12 deletions.
16 changes: 11 additions & 5 deletions src/elf/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,11 @@ impl<'elf, B> Cache<'elf, B> {

let shdrs = if ehdr.is_32bit() {
data.read_pod_slice_ref::<Elf32_Shdr>(ehdr.shnum)
.map(Cow::Borrowed)
.map(ElfN_Shdrs::B32)
} else {
data.read_pod_slice_ref::<Elf64_Shdr>(ehdr.shnum)
.map(Cow::Borrowed)
.map(ElfN_Shdrs::B64)
}
.ok_or_invalid_data(|| "failed to read ELF section headers")?;
Expand All @@ -584,9 +586,11 @@ impl<'elf, B> Cache<'elf, B> {

let phdrs = if ehdr.is_32bit() {
data.read_pod_slice_ref::<Elf32_Phdr>(ehdr.phnum)
.map(Cow::Borrowed)
.map(ElfN_Phdrs::B32)
} else {
data.read_pod_slice_ref::<Elf64_Phdr>(ehdr.phnum)
.map(Cow::Borrowed)
.map(ElfN_Phdrs::B64)
}
.ok_or_invalid_data(|| "failed to read ELF program headers")?;
Expand Down Expand Up @@ -709,9 +713,11 @@ impl<'elf, B> Cache<'elf, B> {
let mut data = self.section_data_raw(idx)?;
let syms = if ehdr.is_32bit() {
data.read_pod_slice_ref::<Elf32_Sym>(count)
.map(Cow::Borrowed)
.map(ElfN_Syms::B32)
} else {
data.read_pod_slice_ref::<Elf64_Sym>(count)
.map(Cow::Borrowed)
.map(ElfN_Syms::B64)
}
.ok_or_invalid_data(|| format!("failed to read ELF {section} symbol table contents"))?;
Expand Down Expand Up @@ -1595,7 +1601,7 @@ mod tests {
#[test]
fn lookup_symbol_without_match() {
let strs = b"\x00_glapi_tls_Context\x00_glapi_get_dispatch_table_size\x00";
let syms = ElfN_Syms::B64(&[
let syms = ElfN_Syms::B64(Cow::Borrowed(&[
Elf64_Sym {
st_name: 0x21,
st_info: 0x12,
Expand All @@ -1621,7 +1627,7 @@ mod tests {
st_value: 0,
st_size: 0,
},
]);
]));
let by_addr_idx = [2, 1, 0];

let result = find_sym(&syms, &by_addr_idx, strs, 0x10d20, SymType::Function).unwrap();
Expand Down Expand Up @@ -1658,7 +1664,7 @@ mod tests {
assert_eq!(result, None);
}

let syms = ElfN_Syms::B64(&[
let syms = ElfN_Syms::B64(Cow::Borrowed(&[
Elf64_Sym {
st_name: 0,
st_info: 0,
Expand All @@ -1683,7 +1689,7 @@ mod tests {
st_value: 0x29d00,
st_size: 0x0,
},
]);
]));
let by_addr_idx = [0, 2, 1];

test(&syms, &by_addr_idx);
Expand Down Expand Up @@ -1765,7 +1771,7 @@ mod tests {
backend: aligned_data,
elf_data: aligned_data,
ehdr: OnceCell::from(ehdr),
shdrs: OnceCell::from(ElfN_Shdrs::B64(shdrs.as_slice())),
shdrs: OnceCell::from(ElfN_Shdrs::B64(Cow::Borrowed(shdrs.as_slice()))),
shstrtab: OnceCell::from(b".shstrtab\x00.symtab\x00".as_slice()),
phdrs: OnceCell::new(),
symtab: OnceCell::new(),
Expand Down
15 changes: 8 additions & 7 deletions src/elf/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ where
#[derive(Debug)]
pub(crate) enum ElfNSlice<'elf, T>
where
T: Has32BitTy,
T: Clone + Has32BitTy,
T::Ty32Bit: Clone,
{
B32(&'elf [T::Ty32Bit]),
B64(&'elf [T]),
B32(Cow<'elf, [T::Ty32Bit]>),
B64(Cow<'elf, [T]>),
}

impl<'elf, T> ElfNSlice<'elf, T>
Expand All @@ -75,17 +76,17 @@ where
{
pub fn empty(tybit32: bool) -> Self {
if tybit32 {
Self::B32(&[])
Self::B32(Cow::Borrowed(&[]))
} else {
Self::B64(&[])
Self::B64(Cow::Borrowed(&[]))
}
}

pub fn is_empty(&self) -> bool {
self.len() == 0
}

pub fn get(&self, idx: usize) -> Option<ElfN<'elf, T>> {
pub fn get(&self, idx: usize) -> Option<ElfN<'_, T>> {
match self {
Self::B32(slice) => Some(ElfN::B32(Cow::Borrowed(slice.get(idx)?))),
Self::B64(slice) => Some(ElfN::B64(Cow::Borrowed(slice.get(idx)?))),
Expand All @@ -99,7 +100,7 @@ where
}
}

pub fn iter(&self, start_idx: usize) -> impl ExactSizeIterator<Item = ElfN<'elf, T>> {
pub fn iter(&self, start_idx: usize) -> impl ExactSizeIterator<Item = ElfN<'_, T>> {
match self {
Self::B32(slice) => Either::A(slice[start_idx..].iter().map(|x| ElfN::B32(Cow::Borrowed(x)))),
Self::B64(slice) => Either::B(slice[start_idx..].iter().map(|x| ElfN::B64(Cow::Borrowed(x)))),
Expand Down

0 comments on commit 306af62

Please sign in to comment.