Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 12 additions & 22 deletions src/print/fuchsia.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use core::fmt::{self, Write};
use core::mem::{size_of, transmute};
use core::slice::from_raw_parts;
use libc::c_char;
use object::NativeEndian as NE;

unsafe extern "C" {
// dl_iterate_phdr takes a callback that will receive a dl_phdr_info pointer
Expand Down Expand Up @@ -118,12 +118,7 @@ const NT_GNU_BUILD_ID: u32 = 3;

// Elf_Nhdr represents an ELF note header in the endianness of the target.
#[allow(non_camel_case_types)]
#[repr(C)]
struct Elf_Nhdr {
n_namesz: u32,
n_descsz: u32,
n_type: u32,
}
type Elf_Nhdr = object::elf::NoteHeader32<NE>;

// Note represents an ELF note (header + contents). The name is left as a u8
// slice because it is not always null terminated and rust makes it easy enough
Expand Down Expand Up @@ -176,19 +171,14 @@ fn take_bytes_align4<'a>(num: usize, bytes: &mut &'a [u8]) -> Option<&'a [u8]> {
Some(out)
}

// This function has no real invariants the caller must uphold other than
// perhaps that 'bytes' should be aligned for performance (and on some
// architectures correctness). The values in the Elf_Nhdr fields might
// be nonsense but this function ensures no such thing.
// This function has no invariants the caller must uphold, but it will return `None`
// if 'bytes' is not correctly aligned. The values in the Elf_Nhdr fields might be
// nonsense but this function ensures no such thing.
fn take_nhdr<'a>(bytes: &mut &'a [u8]) -> Option<&'a Elf_Nhdr> {
if size_of::<Elf_Nhdr>() > bytes.len() {
return None;
}
// This is safe as long as there is enough space and we just confirmed that
// in the if statement above so this should not be unsafe.
let out = unsafe { transmute::<*const u8, &'a Elf_Nhdr>(bytes.as_ptr()) };
// Note that sice_of::<Elf_Nhdr>() is always 4-byte aligned.
*bytes = &bytes[size_of::<Elf_Nhdr>()..];
let (out, rest) = object::pod::from_bytes::<Elf_Nhdr>(bytes).ok()?;
// Note that size_of::<Elf_Nhdr>() is always a multiple of 4-bytes, so the
// 4-byte alignment is maintained.
*bytes = rest;
Some(out)
}

Expand All @@ -204,12 +194,12 @@ impl<'a> Iterator for NoteIter<'a> {
// decisions based on the type. So even if we get out complete garbage
// we should still be safe.
let nhdr = take_nhdr(&mut self.base)?;
let name = take_bytes_align4(nhdr.n_namesz as usize, &mut self.base)?;
let desc = take_bytes_align4(nhdr.n_descsz as usize, &mut self.base)?;
let name = take_bytes_align4(nhdr.n_namesz.get(NE) as usize, &mut self.base)?;
let desc = take_bytes_align4(nhdr.n_descsz.get(NE) as usize, &mut self.base)?;
Some(Note {
name: name,
desc: desc,
tipe: nhdr.n_type,
tipe: nhdr.n_type.get(NE),
})
}
}
Expand Down
Loading