Dynamic Loading Issue at multiple libraries loading the same library
Spotted from python312
recipe. When we're running any module, say python3 -m pip
, relibc will panic:
user:~/public_html$ python3 main.py
RELIBC PANIC: panicked at src/ld_so/dso.rs:969:29:
unresolved symbol: deflateEnd for soname None
I went renaming all python modules to diagnose this issue:
pushd "${COOKBOOK_STAGE}"/usr/lib/python3.12/lib-dynload
for f in *.so; do
echo "Setting SONAME for $f"
patchelf --set-soname "$f" "$f"
done
popd
Then add debugging pointer to ld.so load_object
:
fn load_object(
&mut self,
path: &str,
runpath: &Option<String>,
base_addr: Option<usize>,
dlopened: bool,
resolve: Resolve,
scope: ScopeKind,
) -> Result<Arc<DSO>> {
// ................
for (i, obj) in new_objects.iter().enumerate() {
eprintln!("Relocating {} from {}", obj.name, path); // <-- add this
obj.relocate(&objects_data[i], resolve).unwrap();
}
Then examine the output:
user:~/public_html$ python3 main.py
Relocating libc.so.6 from /usr/bin/python3
Relocating libgcc_s.so.1 from /usr/bin/python3
Relocating libpython3.12.so.1.0 from /usr/bin/python3
Relocating python3 from /usr/bin/python3
Relocating _datetime.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/_datetime.cpython-312-x86_64-redox.so
Relocating math.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/math.cpython-312-x86_64-redox.so
Relocating _bisect.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/_bisect.cpython-312-x86_64-redox.so
Relocating _random.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/_random.cpython-312-x86_64-redox.so
Relocating _sha2.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/_sha2.cpython-312-x86_64-redox.so
Relocating _socket.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/_socket.cpython-312-x86_64-redox.so
Relocating select.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/select.cpython-312-x86_64-redox.so
Relocating array.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/array.cpython-312-x86_64-redox.so
Relocating _struct.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/_struct.cpython-312-x86_64-redox.so
Relocating libz.so.1.3 from /usr/lib/python3.12/lib-dynload/binascii.cpython-312-x86_64-redox.so
Relocating binascii.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/binascii.cpython-312-x86_64-redox.so
Relocating zlib.cpython-312-x86_64-redox.so from /usr/lib/python3.12/lib-dynload/zlib.cpython-312-x86_64-redox.so
RELIBC PANIC: panicked at src/ld_so/dso.rs:969:29:
unresolved symbol: deflateEnd for soname Some("zlib.cpython-312-x86_64-redox.so")
Here we can see that libz.so.1.3
loaded by binascii.cpython-312-x86_64-redox.so
, and it successfully loaded. But when libz.so.1.3
loaded by zlib.cpython-312-x86_64-redox.so
, it panics unable to find deflateEnd
.
Does this function was not loaded on binascii
? Yes
➜ lib-dynload git:(master) ✗ x86_64-unknown-redox-nm -D binascii.cpython-312-x86_64-redox.so | grep deflateEnd
➜ lib-dynload git:(master) ✗ x86_64-unknown-redox-nm -D zlib.cpython-312-x86_64-redox.so | grep deflateEnd
U deflateEnd
So because the first .so
module doesn't load the function needed by second .so
, relibc will panic.
I suspect the loading don't occur because of the first if gate in function of load_objects_recursive
, but I've tried commenting it out, the error got worse. So I decided to stop and raise this issue.
fn load_objects_recursive<'a>(
&mut self,
name: &str,
parent_runpath: &Option<String>,
base_addr: Option<usize>,
dlopened: bool,
new_objects: &mut Vec<Arc<DSO>>,
objects_data: &mut Vec<Vec<ProgramHeader>>,
tcb_masters: &mut Vec<Master>,
// Scope of the object that caused this object to be loaded.
dependent_scope: Option<&mut Scope>,
scope_kind: ScopeKind,
) -> Result<Arc<DSO>> {
// fixme: double lookup slow
if let Some(id) = self.name_to_object_id_map.get(name) {
if let Some(obj) = self.objects.get_mut(id) {
return Ok(obj.clone());
}
} else if let Some(obj) = new_objects.iter_mut().find(|o| o.name == name) {
return Ok(obj.clone());
}