{"record":{"id":"be1a85ab6ddf704b","repo":"Hmbown/CodeWhale","slug":"android-dladdr-could-not-locate-the-updater-s-load","errorCode":null,"errorMessage":"Android dladdr could not locate the updater's loaded image","messagePattern":"Android dladdr could not locate the updater's loaded image","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/update.rs","lineNumber":271,"sourceCode":"#[cfg(target_os = \"android\")]\nfn android_loaded_executable_proof() -> Result<AndroidExecutableProof> {\n    let marker = android_update_image_marker as *const () as usize as u64;\n    let dladdr_path = android_dladdr_path(android_update_image_marker as *const libc::c_void)?;\n    let maps = std::fs::read_to_string(ANDROID_PROC_SELF_MAPS)\n        .context(\"failed to read Android executable mappings from /proc/self/maps\")?;\n    android_loaded_executable_proof_report(&maps, marker, &dladdr_path)\n}\n\n#[cfg(target_os = \"android\")]\nfn android_dladdr_path(marker: *const libc::c_void) -> Result<PathBuf> {\n    use std::os::unix::ffi::OsStrExt;\n\n    let mut info = std::mem::MaybeUninit::<libc::Dl_info>::zeroed();\n    // SAFETY: `marker` points to a function in this loaded image and `info`\n    // points to writable storage for the duration of the call.\n    let found = unsafe { libc::dladdr(marker, info.as_mut_ptr()) };\n    if found == 0 {\n        bail!(\"Android dladdr could not locate the updater's loaded image\");\n    }\n    // SAFETY: A non-zero dladdr result initializes `info`.\n    let info = unsafe { info.assume_init() };\n    if info.dli_fname.is_null() {\n        bail!(\"Android dladdr returned an empty loaded-image path\");\n    }\n    // SAFETY: `dli_fname` is a NUL-terminated string owned by the dynamic\n    // loader and remains valid while this image is loaded.\n    let bytes = unsafe { CStr::from_ptr(info.dli_fname) }.to_bytes();\n    if bytes.is_empty() {\n        bail!(\"Android dladdr returned an empty loaded-image path\");\n    }\n    Ok(PathBuf::from(OsStr::from_bytes(bytes)))\n}\n\n#[cfg(any(target_os = \"android\", all(test, unix)))]\n#[derive(Debug, Clone, PartialEq, Eq)]\nstruct AndroidImageMapping {","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/cli/src/update.rs#L253-L289","documentation":"On Android, the self-updater needs the filesystem path of its own loaded image and asks the dynamic loader via `dladdr(marker, &info)`, where `marker` is a function pointer inside this binary. A zero return means dladdr could not resolve even that address to a loaded object — typically caused by static linking, symbol stripping, or an unusual loader configuration — so the updater cannot locate the APK/embedded library to replace.","triggerScenarios":"Running `codewhale update` in a Termux/proot or embedded Android environment where the binary is statically linked or its symbols are stripped such that dladdr fails on the marker function.","commonSituations":"Codewhale built with a static/musl-like toolchain on Android; `-s`/strip'd builds; loaders (e.g. certain proot setups) that do not register images with dladdr; hardened environments hiding link maps.","solutions":["Update outside the dladdr path: reinstall/upgrade via your package source (e.g. Termux package manager) instead of self-update","Rebuild/install an unstripped, dynamically linked codewhale binary on the device and retry self-update","Report the environment details (device, linker, build flags) upstream — this is an unsupported-loader bug worth filing"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"#!/usr/bin/env bash\n# on Android, prefer package-manager updates over self-update\nif [ \"$(uname -o 2>/dev/null || uname)\" = \"Android\" ]; then\n  pkg upgrade codewhale 2>/dev/null || echo \"self-update may fail on this loader; use manual install\" >&2\nelse\n  codewhale update\nfi","typeGuard":null,"tryCatchPattern":"# shell: fall back to manual install when self-update cannot locate its image\nif ! codewhale update; then\n  echo \"self-update unavailable; installing verified release manually\" >&2\n  curl -fLO <official-release-url>/codewhale-android-arm64\n  # verify checksum, then replace the binary on PATH\nfi","preventionTips":["On Android, install codewhale via the package manager and disable self-update","Keep the deployed binary dynamically linked and unstripped if self-update is required","Automate updates off-device (download, verify, push) rather than in-place on Android"],"tags":["android","dladdr","self-update","linker","ffi","platform"],"backgroundTag":"dladdr-failed","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}