rust-lang/rust · error

const_alloc_to_gcc_uncached: could not read relocation point

Error message

const_alloc_to_gcc_uncached: could not read relocation pointer

What it means

`const_alloc_to_gcc_uncached` (consts.rs:315-348) walks an allocation's provenance pointers and, for each, reads `pointer_size` bytes as a target-endian integer via `read_target_uint(dl.endian, ...).expect("const_alloc_to_gcc_uncached: could not read relocation pointer")` at line 347. The panic means those bytes could not be decoded into a `u64` relocation offset. This is an interpreter/codegen contract violation: the provenance range must contain exactly a pointer-sized, endian-correct integer.

Source

Thrown at compiler/rustc_codegen_gcc/src/consts.rs:347

        let offset = offset as usize;
        if offset > next_offset {
            // This `inspect` is okay since we have checked that it is not within a pointer with provenance, it
            // is within the bounds of the allocation, and it doesn't affect interpreter execution
            // (we inspect the result after interpreter execution). Any undef byte is replaced with
            // some arbitrary byte value.
            //
            // FIXME: relay undef bytes to codegen as undef const bytes
            let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset);
            llvals.push(cx.const_bytes(bytes));
        }
        let ptr_offset = read_target_uint(
            dl.endian,
            // This `inspect` is okay since it is within the bounds of the allocation, it doesn't
            // affect interpreter execution (we inspect the result after interpreter execution),
            // and we properly interpret the provenance as a relocation pointer offset.
            alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
        )
        .expect("const_alloc_to_gcc_uncached: could not read relocation pointer")
            as u64;

        let address_space = cx.tcx.global_alloc(alloc_id).address_space(cx);

        llvals.push(cx.scalar_to_backend(
            InterpScalar::from_pointer(
                interpret::Pointer::new(prov, Size::from_bytes(ptr_offset)),
                &cx.tcx,
            ),
            abi::Scalar::Initialized {
                value: Primitive::Pointer(address_space),
                valid_range: WrappingRange::full(dl.pointer_size()),
            },
            cx.type_i8p_ext(address_space),
        ));
        next_offset = offset + pointer_size;
    }
    if alloc.len() >= next_offset {

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Clean incremental artifacts (`cargo clean` / remove `target/`) and rebuild — a stale corrupt allocation cache is a cheap first check.
  2. Verify the target triple and data layout match the pointer width the code was compiled for; a 64-bit target with a 32-bit-pointer data layout (or vice versa) is the usual cause.
  3. Reproduce against the rustc version this rustc_codegen_gcc checkout is pinned to; provenance encoding has changed across rustc releases.
  4. If you control the target spec, confirm `data_layout` pointer size and endianness are correct; dump the bytes at the failing offset and compare to the expected relocation value.

Example fix

// before (consts.rs:340-348)
let ptr_offset = read_target_uint(
    dl.endian,
    alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
)
.expect("const_alloc_to_gcc_uncached: could not read relocation pointer") as u64;

// after (diagnose pointer-size / endianness mismatch instead of opaque panic)
let reloc_bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size));
let ptr_offset = read_target_uint(dl.endian, reloc_bytes).unwrap_or_else(|e| {
    panic!("relocation read failed at offset {offset}: pointer_size={pointer_size}, endian={:?}, bytes={reloc_bytes:?}, err={e:?}", dl.endian);
}) as u64;
Defensive patterns

Strategy: validation

Validate before calling

// consts.rs:347 -> read_target_uint over the relocation slot panics if the
// byte slice is shorter than pointer_size or the offset is out of bounds.
// Validate the allocation window before const lowering:
fn reloc_slot_ok(alloc_bytes: &[u8], offset: usize, ptr_size: usize) -> bool {
    match offset.checked_add(ptr_size) {
        Some(end) => end <= alloc_bytes.len(),
        None => false,
    }
}
// Also confirm dl.endian and pointer_size match the target data layout.

Prevention

When it happens

Trigger: Reached when an allocation has provenance (`alloc.provenance().ptrs()` non-empty) and `read_target_uint` overflows or otherwise fails on the bytes at `[offset, offset+pointer_size)`. Concretely: pointer-size mismatch (e.g. the data layout's `pointer_size` differs from what the interpreter wrote), a truncated/corrupt allocation buffer, or an unsupported relocation encoding for the target's endianness.

Common situations: Cross-compiling between pointer-width targets (32 vs 64-bit) with a misconfigured target spec / data layout; using a rustc version whose const-eval writes provenance in a shape this backend doesn't expect; corrupted incremental-cache artifacts; custom targets with non-standard pointer sizes.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/eeea581f847005fe.json. Report an issue: GitHub.