Hmbown/CodeWhale · critical

Android loaded-image authorities resolved to runtime linker

Error message

Android loaded-image authorities resolved to runtime linker {}; refusing to use the linker as an update target

What it means

Even when dladdr and /proc/self/maps agree, the resolved loaded image could be the runtime linker itself (e.g. /system/bin/linker64) rather than the updater binary — which happens when the marker address maps into the linker's own text. The updater refuses to use the linker as an update target because overwriting the linker would brick dynamic execution on the device.

Solutions

  1. Run the updater binary normally (exec it directly, not via the linker/loader explicitly).
  2. Rebuild or re-install the binary so its text does not resolve into the linker's mapping; verify with `readelf -l` where the entry point sits.
  3. Ensure the release binary being updated is the actual updater executable, not a stub launched through the linker.
  4. If hit reproducibly on a specific build, report the build/link flags upstream — the marker function placement is pathological.

Example fix

// before: launching via the loader
/system/bin/linker64 $PREFIX/bin/codewhale update
// after: execute the binary directly
$PREFIX/bin/codewhale update
Defensive patterns

Strategy: validation

Validate before calling

const LINKER_NAMES: [&str; 3] = ["linker", "linker64", "linker64-4"];
fn looks_like_linker(p: &std::path::Path) -> bool {
    p.file_name().and_then(|n| n.to_str())
        .map(|n| LINKER_NAMES.iter().any(|l| n.starts_with(l)))
        .unwrap_or(false)
}
if looks_like_linker(&resolved_path) { return Err(anyhow!("resolved to runtime linker")); }

Prevention

When it happens

Trigger: android_loaded_executable_proof when is_android_linker_name() matches the canonically-resolved path from both authorities.

Common situations: Marker function inlined or placed in a section that resolves into the linker's mapping; running the binary via an unusual loader invocation (e.g. `/system/bin/linker64 ./binary`); builds with PIE/linker-script oddities on Android.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/ca695078ffb6d0f0. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/update.rs:456

            "failed to canonicalize Android dladdr path {}",
            dladdr_path.display()
        )
    })?;
    let resolved_mapping = mapping.path.canonicalize().with_context(|| {
        format!(
            "failed to canonicalize Android loaded-image mapping {}",
            mapping.path.display()
        )
    })?;
    if resolved_dladdr != resolved_mapping {
        bail!(
            "Android loaded-image authorities disagree: dladdr resolved to {}, but /proc/self/maps resolved to {}",
            resolved_dladdr.display(),
            resolved_mapping.display()
        );
    }
    if is_android_linker_name(&resolved_mapping) {
        bail!(
            "Android loaded-image authorities resolved to runtime linker {}; refusing to use the linker as an update target",
            resolved_mapping.display()
        );
    }
    if !is_executable_file(&resolved_mapping) {
        bail!(
            "Android loaded image `{}` is not an executable regular file; refusing to select an update target",
            resolved_mapping.display()
        );
    }

    validate_android_mapping_identity(&mapping, &resolved_mapping)?;
    Ok(AndroidExecutableProof {
        path: resolved_mapping,
        device_major: mapping.device_major,
        device_minor: mapping.device_minor,
        inode: mapping.inode,
        proof_kind: AndroidExecutableProofKind::DladdrAndProcMaps,

View on GitHub (pinned to 73e0f67d83)