Merge branch 'ld.so_regressions' into 'master'

Ld.so regressions

See merge request redox-os/relibc!268
This commit is contained in:
Jeremy Soller
2020-05-03 13:16:43 +00:00
2 changed files with 74 additions and 24 deletions
+14 -1
View File
@@ -52,6 +52,16 @@ impl RTLDDebug {
}
return;
}
pub fn insert_first(&mut self, l_addr: usize, name: &str, l_ld: usize) {
if self.r_map.is_null() {
self.r_map = LinkMap::new_with_args(l_addr, name, l_ld);
} else {
let tmp = self.r_map;
self.r_map = LinkMap::new_with_args(l_addr, name, l_ld);
unsafe { (*self.r_map).link(&mut *tmp) };
}
return;
}
}
#[repr(C)]
@@ -80,7 +90,10 @@ impl LinkMap {
});
Box::into_raw(map)
}
fn link(&mut self, map: &mut LinkMap) {
map.l_prev = self as *mut LinkMap;
self.l_next = map as *mut LinkMap;
}
fn new_with_args(l_addr: usize, name: &str, l_ld: usize) -> *mut Self {
let map = LinkMap::new();
unsafe {
+60 -23
View File
@@ -383,7 +383,6 @@ impl Linker {
}
// Allocate memory
let mmap = unsafe {
let size = bounds.1 /* - bounds.0 */;
let same_elf = if let Some(prog) = dso.as_ref() {
if prog.name == *elf_name {
true
@@ -395,14 +394,45 @@ impl Linker {
};
if same_elf {
let addr = dso.as_ref().unwrap().base_addr;
let mut size = bounds.1;
// Fill the gaps i the binary
let mut ranges = Vec::new();
for ph in elf.program_headers.iter() {
if ph.p_type == program_header::PT_LOAD {
let voff = ph.p_vaddr as usize % PAGE_SIZE;
let vaddr = ph.p_vaddr as usize - voff;
let vsize = ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE)
* PAGE_SIZE;
ranges.push((vaddr, vsize));
}
}
ranges.sort();
let mut start = addr;
for (vaddr, vsize) in ranges.iter() {
if start < addr + vaddr {
let gap_size = addr + vaddr - start;
size += gap_size;
sys_mman::mmap(
start as *mut c_void,
addr + vaddr - start,
//TODO: Make it possible to not specify PROT_EXEC on Redox
sys_mman::PROT_READ | sys_mman::PROT_WRITE,
sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE,
-1,
0,
);
}
start = addr + vaddr + vsize
}
sys_mman::mprotect(
addr as *mut c_void,
size,
sys_mman::PROT_READ | sys_mman::PROT_WRITE,
);
_r_debug.insert(addr as usize, &elf_name, addr + l_ld as usize);
_r_debug.insert_first(addr as usize, &elf_name, addr + l_ld as usize);
slice::from_raw_parts_mut(addr as *mut u8, size)
} else {
let size = bounds.1;
let ptr = sys_mman::mmap(
ptr::null_mut(),
size,
@@ -659,29 +689,36 @@ impl Linker {
}
}
// overwrite DT_DEBUG if exist in .dynamic section
for section in &elf.section_headers {
// we won't bother with half corrupted elfs.
let name = elf.shdr_strtab.get(section.sh_name).unwrap().unwrap();
if name != ".dynamic" {
continue;
// overwrite DT_DEBUG if exist in DYNAMIC segment
// first we identify the location of DYNAMIC segment
let mut dyn_start = None;
let mut debug_start = None;
for ph in elf.program_headers.iter() {
if ph.p_type == program_header::PT_DYNAMIC {
dyn_start = Some(ph.p_vaddr as usize);
}
let mmap = match self.mmaps.get_mut(*elf_name) {
Some(some) => some,
None => continue,
};
let dyn_start = section.sh_addr as usize;
let bytes: [u8; size_of::<Dyn>() / 2] =
unsafe { transmute((&_r_debug) as *const RTLDDebug as usize) };
if let Some(dynamic) = elf.dynamic.as_ref() {
let mut i = 0;
for entry in &dynamic.dyns {
if entry.d_tag == DT_DEBUG {
let start = dyn_start + i * size_of::<Dyn>() + size_of::<Dyn>() / 2;
mmap[start..start + size_of::<Dyn>() / 2].clone_from_slice(&bytes);
}
i += 1;
}
// next we identify the location of DT_DEBUG in .dynamic section
if let Some(dynamic) = elf.dynamic.as_ref() {
let mut i = 0;
for entry in &dynamic.dyns {
if entry.d_tag == DT_DEBUG {
debug_start = Some(i as usize);
break;
}
i += 1;
}
}
if let Some(dyn_start_addr) = dyn_start {
if let Some(i) = debug_start {
let mmap = match self.mmaps.get_mut(*elf_name) {
Some(some) => some,
None => continue,
};
let bytes: [u8; size_of::<Dyn>() / 2] =
unsafe { transmute((&_r_debug) as *const RTLDDebug as usize) };
let start = dyn_start_addr + i * size_of::<Dyn>() + size_of::<Dyn>() / 2;
mmap[start..start + size_of::<Dyn>() / 2].clone_from_slice(&bytes);
}
}