Skip to content

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());
        }
Edited by Wildan Mubarok