This patch makes a consistent choice of rounded_last_vaddr vs last_vaddr for moving the initial segments. The choice is between adding a new page after the moved segments for the modified sections, vs concatenating. The main thing to consider is page permissions, which are likely to be different between dynamic linking info vs core program info.
E6W7X7U3IC5542LG2KFLCFIVWZS4BSNT4KF7FRKCM6XVZTN3CNJAC
pub fn dynsym(&self) -> Dynsym {
let header = self.header();
let id = self.id();
let names = self.names(id.data, &header).unwrap();
for i in 0..header.shnum(id.data) {
let s = self.section(i as usize).unwrap();
let name = names.name(s.name(id.data) as usize).unwrap();
if name.to_bytes() == b".dynsym" {
let offset = s.offset(id.data) as usize;
let size = s.size(id.data) as usize;
if id.class == Bits::B32 {
return Dynsym::B32(unsafe {
std::slice::from_raw_parts(
self.map.as_ptr().add(offset) as *const u8 as *const Elf32Sym,
size / std::mem::size_of::<Elf32Sym>(),
)
})
} else if id.class == Bits::B64 {
return Dynsym::B64(unsafe {
std::slice::from_raw_parts(
self.map.as_ptr().add(offset) as *const u8 as *const Elf64Sym,
size / std::mem::size_of::<Elf64Sym>(),
)
})
}
}
}
Dynsym::B64(&[])
}
pub fn verneed(&self) -> Vec<(Verneed, Vec<Vernaux>)> {
let header = self.header();
let id = self.id();
let names = self.names(id.data, &header).unwrap();
let mut result = Vec::new();
for i in 0..header.shnum(id.data) {
let s = self.section(i as usize).unwrap();
let name = names.name(s.name(id.data) as usize).unwrap();
if name.to_bytes() == b".gnu.version_r" {
let offset = s.offset(id.data) as usize;
let size = s.size(id.data) as usize;
unsafe {
let mut current = self.map.as_ptr().add(offset) as *const u8;
loop {
assert!((current as usize) < offset + size);
let mut aux = Vec::new();
let mut aux_ptr = current.add((&*(current as *const Verneed)).aux as usize) as *const u8;
loop {
assert!((aux_ptr as usize) < offset + size);
aux.push(*(aux_ptr as *const Vernaux));
let next = (&*(aux_ptr as *const Vernaux)).next as usize;
if next == 0 {
break
}
aux_ptr = aux_ptr.add(next);
}
result.push((*(current as *const Verneed), aux));
let next = (&*(current as *const Vernaux)).next as usize;
if next == 0 {
break
}
current = current.add(next);
}
}
}
}
result
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Elf32Sym {
name: Endian<u32>,
value: Endian<u32>,
size: Endian<u32>,
info: u8,
other: u8,
shndx: Endian<u16>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Elf64Sym {
name: Endian<u32>,
info: u8,
other: u8,
shndx: Endian<u16>,
value: Endian<u64>,
size: Endian<u64>,
}
#[derive(Debug)]
pub enum Dynsym<'a> {
B32(&'a [Elf32Sym]),
B64(&'a [Elf64Sym]),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Verneed {
version: u16,
cnt: u16,
file: u32,
aux: u32,
next: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Vernaux {
hash: u32,
flags: u16,
other: u16,
name: u32,
next: u32,
}