Merge branch 'patch5' into 'master'
feat(ld.so): add support for DT_RELR See merge request redox-os/relibc!602
This commit is contained in:
@@ -168,6 +168,19 @@ test: sysroot
|
||||
$(MAKE) -C tests run
|
||||
$(MAKE) -C tests verify
|
||||
|
||||
|
||||
$(BUILD)/$(PROFILE)/libc.so: $(BUILD)/$(PROFILE)/librelibc.a $(BUILD)/openlibm/libopenlibm.a
|
||||
$(CC) -nostdlib \
|
||||
-shared \
|
||||
-Wl,--gc-sections \
|
||||
-Wl,-z,pack-relative-relocs \
|
||||
-Wl,--sort-common \
|
||||
-Wl,--allow-multiple-definition \
|
||||
-Wl,--whole-archive $^ -Wl,--no-whole-archive \
|
||||
-Wl,-soname,libc.so.6 \
|
||||
-lgcc \
|
||||
-o $@
|
||||
|
||||
# Debug targets
|
||||
|
||||
$(BUILD)/debug/libc.a: $(BUILD)/debug/librelibc.a $(BUILD)/openlibm/libopenlibm.a
|
||||
@@ -179,9 +192,6 @@ $(BUILD)/debug/libc.a: $(BUILD)/debug/librelibc.a $(BUILD)/openlibm/libopenlibm.
|
||||
echo "end" >> "$@.mri"
|
||||
$(AR) -M < "$@.mri"
|
||||
|
||||
$(BUILD)/debug/libc.so: $(BUILD)/debug/librelibc.a $(BUILD)/openlibm/libopenlibm.a
|
||||
$(CC) -nostdlib -shared -Wl,--allow-multiple-definition -Wl,--whole-archive $^ -Wl,--no-whole-archive -Wl,-soname,libc.so.6 -lgcc -o $@
|
||||
|
||||
$(BUILD)/debug/librelibc.a: $(SRC)
|
||||
$(CARGO) rustc $(CARGOFLAGS) -- --emit link=$@ -g -C debug-assertions=no $(RUSTCFLAGS)
|
||||
./renamesyms.sh "$@" "$(BUILD)/debug/deps/"
|
||||
@@ -217,9 +227,6 @@ $(BUILD)/release/libc.a: $(BUILD)/release/librelibc.a $(BUILD)/openlibm/libopenl
|
||||
echo "end" >> "$@.mri"
|
||||
$(AR) -M < "$@.mri"
|
||||
|
||||
$(BUILD)/release/libc.so: $(BUILD)/release/librelibc.a $(BUILD)/openlibm/libopenlibm.a
|
||||
$(CC) -nostdlib -shared -Wl,--allow-multiple-definition -Wl,--whole-archive $^ -Wl,--no-whole-archive -Wl,-soname,libc.so.6 -lgcc -o $@
|
||||
|
||||
$(BUILD)/release/librelibc.a: $(SRC)
|
||||
$(CARGO) rustc --release $(CARGOFLAGS) -- --emit link=$@ $(RUSTCFLAGS)
|
||||
# TODO: Better to only allow a certain whitelisted set of symbols? Perhaps
|
||||
|
||||
+58
-9
@@ -8,7 +8,7 @@ use object::{
|
||||
Dyn as _, GnuHashTable, HashTable as SysVHashTable, ProgramHeader as _, Rel as _,
|
||||
Rela as _, Sym as _, Version, VersionTable,
|
||||
},
|
||||
Endianness, NativeEndian, Object, StringTable, SymbolIndex,
|
||||
NativeEndian, Object, StringTable, SymbolIndex,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -27,11 +27,15 @@ use alloc::{
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{
|
||||
ffi::c_char,
|
||||
mem::size_of,
|
||||
ptr::{self, NonNull},
|
||||
slice,
|
||||
};
|
||||
|
||||
pub const CHAR_BITS: usize = size_of::<c_char>() * 8;
|
||||
pub type Relr = usize;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
mod shim {
|
||||
use object::{elf::*, read::elf::ElfFile32, NativeEndian};
|
||||
@@ -129,6 +133,7 @@ pub(super) struct Dynamic<'data> {
|
||||
init_array: &'data [unsafe extern "C" fn()],
|
||||
fini_array: &'data [unsafe extern "C" fn()],
|
||||
rela: &'data [Rela],
|
||||
relr: &'data [Relr],
|
||||
rel: &'data [Rel],
|
||||
symbols: &'data [Sym],
|
||||
explicit_addend: bool,
|
||||
@@ -545,6 +550,10 @@ impl DSO {
|
||||
is_pie: bool,
|
||||
(_, entries): (&ProgramHeader, &[Dyn]),
|
||||
) -> object::Result<(Dynamic<'a>, Option<usize>)> {
|
||||
const DT_RELRSZ: u32 = 35;
|
||||
const DT_RELR: u32 = 36;
|
||||
const DT_RELRENT: u32 = 37;
|
||||
|
||||
let mut runpath = None;
|
||||
let mut got = None;
|
||||
let mut needed = vec![];
|
||||
@@ -555,11 +564,12 @@ impl DSO {
|
||||
let mut pltrelsz = None;
|
||||
let mut debug = None;
|
||||
let mut symtab_ptr = None;
|
||||
let (mut rel_ptr, mut rel_size) = (None, None);
|
||||
let (mut rel_ptr, mut rel_len) = (None, None);
|
||||
let (mut relr_ptr, mut relr_len) = (None, None);
|
||||
let (mut strtab_offset, mut strtab_size) = (None, None);
|
||||
let (mut init_array_ptr, mut init_array_len) = (None, None);
|
||||
let (mut fini_array_ptr, mut fini_array_len) = (None, None);
|
||||
let (mut rela_offset, mut rela_size) = (None, None);
|
||||
let (mut rela_offset, mut rela_len) = (None, None);
|
||||
|
||||
for (i, entry) in entries.iter().enumerate() {
|
||||
let val = entry.d_val(NativeEndian);
|
||||
@@ -599,15 +609,21 @@ impl DSO {
|
||||
elf::DT_SONAME => soname = Some(entry),
|
||||
|
||||
elf::DT_RELA => rela_offset = Some(ptr.cast::<Rela>()),
|
||||
elf::DT_RELASZ => rela_size = Some(val as usize / size_of::<Rela>()),
|
||||
elf::DT_RELASZ => rela_len = Some(val as usize / size_of::<Rela>()),
|
||||
elf::DT_RELAENT => {
|
||||
assert_eq!(val as usize, size_of::<elf::Rela64<Endianness>>())
|
||||
assert_eq!(val, size_of::<Rela>() as u64)
|
||||
}
|
||||
|
||||
elf::DT_REL => rel_ptr = Some(ptr.cast::<Rel>()),
|
||||
elf::DT_RELSZ => rel_size = Some(val as usize / size_of::<Rel>()),
|
||||
elf::DT_RELSZ => rel_len = Some(val as usize / size_of::<Rel>()),
|
||||
elf::DT_RELENT => {
|
||||
assert_eq!(val as usize, size_of::<elf::Rel64<Endianness>>())
|
||||
assert_eq!(val, size_of::<Rel>() as u64)
|
||||
}
|
||||
|
||||
DT_RELR => relr_ptr = Some(ptr.cast::<Relr>()),
|
||||
DT_RELRSZ => relr_len = Some(val as usize / size_of::<Relr>()),
|
||||
DT_RELRENT => {
|
||||
assert_eq!(val, size_of::<Relr>() as u64)
|
||||
}
|
||||
|
||||
elf::DT_PLTREL => {
|
||||
@@ -680,8 +696,9 @@ impl DSO {
|
||||
|
||||
let init_array = unsafe { get_array(init_array_ptr, init_array_len) };
|
||||
let fini_array = unsafe { get_array(fini_array_ptr, fini_array_len) };
|
||||
let rela = unsafe { get_array(rela_offset, rela_size) };
|
||||
let rel = unsafe { get_array(rel_ptr, rel_size) };
|
||||
let rela = unsafe { get_array(rela_offset, rela_len) };
|
||||
let relr = unsafe { get_array(relr_ptr, relr_len) };
|
||||
let rel = unsafe { get_array(rel_ptr, rel_len) };
|
||||
|
||||
Ok((
|
||||
Dynamic {
|
||||
@@ -697,6 +714,7 @@ impl DSO {
|
||||
fini_array,
|
||||
rela,
|
||||
rel,
|
||||
relr,
|
||||
explicit_addend: explicit_addend.unwrap_or_default(),
|
||||
pltrelsz: pltrelsz.unwrap_or_default(),
|
||||
},
|
||||
@@ -836,6 +854,37 @@ impl DSO {
|
||||
|
||||
pub fn relocate(&self, ph: &[ProgramHeader], resolve: Resolve) -> object::Result<()> {
|
||||
let global_scope = GLOBAL_SCOPE.read();
|
||||
let base = self.mmap.as_ptr();
|
||||
|
||||
// Apply DT_RELR relative relocations.
|
||||
let mut addr = ptr::null_mut();
|
||||
for &entry in self.dynamic.relr {
|
||||
if entry & 1 == 0 {
|
||||
// An even entry sets up `addr` for subsequent odd entries.
|
||||
unsafe {
|
||||
addr = base.add(entry as usize) as *mut usize;
|
||||
*addr += base as usize;
|
||||
addr = addr.add(1);
|
||||
}
|
||||
} else {
|
||||
// An odd entry indicates a bitmap describing at maximum 63
|
||||
// (for 64-bit) or 31 (for 32-bit) locations following `addr`.
|
||||
// Odd entries can be chained.
|
||||
let mut entry = entry >> 1;
|
||||
let mut i = 0;
|
||||
while entry != 0 {
|
||||
if entry & 1 != 0 {
|
||||
unsafe {
|
||||
*addr.add(i) += base as usize;
|
||||
}
|
||||
}
|
||||
entry >>= 1;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
addr = unsafe { addr.add(CHAR_BITS * size_of::<Relr>() - 1) };
|
||||
}
|
||||
}
|
||||
|
||||
self.dynamic
|
||||
.static_relocations()
|
||||
|
||||
Reference in New Issue
Block a user