[BUG] Symbol-only relocations incorrectly apply the RELA addend #2

Open
opened 2026-09-16 06:34:09 +02:00 by erikinkinen · 0 comments
Owner

Summary

The native link planner applies the RELA addend to R_X86_64_GLOB_DAT and R_X86_64_JUMP_SLOT. The x86-64 psABI defines both values as the resolved symbol value S. With a nonzero unused addend, an otherwise accepted graph produces a different pointer value. R_X86_64_64 legitimately uses S + A and must retain that behavior.

Reproduction

At a278c01e4e1b8606cf4d8ebbfd562bbe74843180, use two independent unit tests in a child module of the existing fixture tests. For each relocation kind, construct fixture_with_dependencies(&[], "defined", None, &[(0x3000, kind, 1, 16)], 0x2000). Validate that fixture with the empty dependency manifest and create one GraphObject with base 0x40000000 and a writable eight-byte target at 0x40003000. Call graph_with_storage and assert that the first write value equals 0x40002000.

Both independent tests fail deterministically with the original production source. The host probes execute no target artifact and acquire no guest capability.

Expected and actual behavior

Expected for both GLOB_DAT and JUMP_SLOT: 0x40002000 (S), regardless of the unused addend field. Actual: 0x40002010 (S + 16). Both focused assertions fail; Cargo exits 101 with zero tests passed and two failed. Existing fixtures use zero addends and therefore do not distinguish these operations from absolute relocation.

The correction should separate the two symbol-only operations from R_X86_64_64. Preserve checked load-bias addition, absolute/relative signed-addend arithmetic, symbol selection, duplicate/missing-symbol rejection and relocation target ownership. Do not infer a new symbol provider or relax target bounds.

Environment and identity

  • Repository and exact production source: lib-dynlink a278c01e4e1b8606cf4d8ebbfd562bbe74843180, also selected by the retained native artifact graph.
  • Host: x86-64 Linux, Rust 1.97.1; warning-denied tests, private dependency-free offline lock and unchanged production source.
  • Input: one literal defined symbol, one caller-supplied graph object and one writable relocation range; no executable/image is run.
  • No guest failure, authority consequence or previously working revision has been established.

Evidence and prior checks

The independent probes retain exact original source hashes and both assertion diagnostics: actual decimal 1073750032 versus expected 1073750016. An initial locked invocation could not create the private fixture's absent lockfile; after offline lock generation, the actual two-test reproduction above ran to completion. That setup refusal is not counted as a reproduced defect.

The primary x86-64 psABI relocation table distinguishes GLOB_DAT/JUMP_SLOT (S) from absolute 64-bit relocation (S + A). The currently admitted frame inspector uses symbolic writes only as footprints and never treats their addends as local call targets, so it does not claim to resolve this mismatch.

Add positive and negative addends for both symbol-only operations, defined/imported and weak-zero symbols, plus absolute/relative overflow controls. Run strict crate validation and matching CI, then audit consumers before any coherent catalog adoption.

Symbol-only relocation correction — 16 September 2026: signed lib-dynlink abd5153adf994ca40753f9650a675940a228e1d3 calculates GLOB_DAT and eager JUMP_SLOT as S, while retaining checked S+A and B+A, original provider selection and writable target ownership. The canonical defect report is #2 and review is #3. Four default/all-feature dev/release configurations pass 47 tests each, host/native strict Clippy, private rustdoc and four native builds without warnings. Of nine new independent controls, five fail and four pass against the original implementation; all nine pass after correction.

Original dynlinkd, loaderd and bootloader source candidates, each changing only the library's full commit selector in an isolated exact-commit worktree, pass four strict configurations: 13/105/41 tests respectively, with twelve native builds and private rustdoc, zero warnings. Published consumer commits remain unchanged pending coherent adoption.

The retained Exsh executable and six explicit libraries yield 1,608 independently expected relocation writes under caller-selected hypothetical load biases. Both original and corrected planners match those original zero-addend inputs. All 107 symbol-only writes remain identical under positive, negative and extreme unused-addend variants with the fix; the original planner fails the addend-16 control (actual Cargo exit 101). The original/packaged dynamic tables are byte-identical and all artifact/manifest hashes are retained. This host metadata replay performs no target mapping or execution and does not admit native frame paths.

Signed Docs 214b08666b8b36ad4270bcfee3b3379d8dc08a79 documents the expressions and regenerates only the library's 103-route API reference from exact signed-source rustdoc JSON. All 45 documentation tests, Markdown and canonical checks pass. The full manual has 2,383 pages, 436,424 in-bounds word boxes, zero final warnings and four visually reviewed changed pages. All 3,696 inventoried code/configuration files remain below 1,000 lines; complete semantic authority and private documentation closure remains open.

Matching library CI 30/31 passes with four complete logs (36,856 bytes), 47 tests per run, strict builds/rustdoc and zero warnings. Docs CI 913/914 passes with four complete logs (763,872 bytes), 45 tests and 2,383-page renders, zero final warnings. Coherent catalog adoption, complete native source/frame evidence, runnable realms and both full guest build generations remain open.

Tracking

Authority and quality audit: #1. Related native frame work: erix/exsh#2 and erix/exsh#4. Keep this defect separate from guest timeout and layout-adoption reports. A correction must retain the existing authority and write-range contracts.

## Summary The native link planner applies the RELA addend to `R_X86_64_GLOB_DAT` and `R_X86_64_JUMP_SLOT`. The x86-64 psABI defines both values as the resolved symbol value S. With a nonzero unused addend, an otherwise accepted graph produces a different pointer value. `R_X86_64_64` legitimately uses S + A and must retain that behavior. ## Reproduction At `a278c01e4e1b8606cf4d8ebbfd562bbe74843180`, use two independent unit tests in a child module of the existing fixture tests. For each relocation kind, construct `fixture_with_dependencies(&[], "defined", None, &[(0x3000, kind, 1, 16)], 0x2000)`. Validate that fixture with the empty dependency manifest and create one `GraphObject` with base `0x40000000` and a writable eight-byte target at `0x40003000`. Call `graph_with_storage` and assert that the first write value equals `0x40002000`. Both independent tests fail deterministically with the original production source. The host probes execute no target artifact and acquire no guest capability. ## Expected and actual behavior Expected for both GLOB_DAT and JUMP_SLOT: `0x40002000` (S), regardless of the unused addend field. Actual: `0x40002010` (S + 16). Both focused assertions fail; Cargo exits 101 with zero tests passed and two failed. Existing fixtures use zero addends and therefore do not distinguish these operations from absolute relocation. The correction should separate the two symbol-only operations from `R_X86_64_64`. Preserve checked load-bias addition, absolute/relative signed-addend arithmetic, symbol selection, duplicate/missing-symbol rejection and relocation target ownership. Do not infer a new symbol provider or relax target bounds. ## Environment and identity - Repository and exact production source: lib-dynlink `a278c01e4e1b8606cf4d8ebbfd562bbe74843180`, also selected by the retained native artifact graph. - Host: x86-64 Linux, Rust 1.97.1; warning-denied tests, private dependency-free offline lock and unchanged production source. - Input: one literal defined symbol, one caller-supplied graph object and one writable relocation range; no executable/image is run. - No guest failure, authority consequence or previously working revision has been established. ## Evidence and prior checks The independent probes retain exact original source hashes and both assertion diagnostics: actual decimal 1073750032 versus expected 1073750016. An initial locked invocation could not create the private fixture's absent lockfile; after offline lock generation, the actual two-test reproduction above ran to completion. That setup refusal is not counted as a reproduced defect. The primary [x86-64 psABI relocation table](https://gitlab.com/x86-psABIs/x86-64-ABI/-/raw/master/x86-64-ABI/object-files.tex) distinguishes GLOB_DAT/JUMP_SLOT (S) from absolute 64-bit relocation (S + A). The currently admitted frame inspector uses symbolic writes only as footprints and never treats their addends as local call targets, so it does not claim to resolve this mismatch. Add positive and negative addends for both symbol-only operations, defined/imported and weak-zero symbols, plus absolute/relative overflow controls. Run strict crate validation and matching CI, then audit consumers before any coherent catalog adoption. Symbol-only relocation correction — 16 September 2026: signed lib-dynlink `abd5153adf994ca40753f9650a675940a228e1d3` calculates GLOB_DAT and eager JUMP_SLOT as S, while retaining checked S+A and B+A, original provider selection and writable target ownership. The canonical defect report is https://git.erikinkinen.fi/erix/lib-dynlink/issues/2 and review is https://git.erikinkinen.fi/erix/lib-dynlink/pulls/3. Four default/all-feature dev/release configurations pass 47 tests each, host/native strict Clippy, private rustdoc and four native builds without warnings. Of nine new independent controls, five fail and four pass against the original implementation; all nine pass after correction. Original dynlinkd, loaderd and bootloader source candidates, each changing only the library's full commit selector in an isolated exact-commit worktree, pass four strict configurations: 13/105/41 tests respectively, with twelve native builds and private rustdoc, zero warnings. Published consumer commits remain unchanged pending coherent adoption. The retained Exsh executable and six explicit libraries yield 1,608 independently expected relocation writes under caller-selected hypothetical load biases. Both original and corrected planners match those original zero-addend inputs. All 107 symbol-only writes remain identical under positive, negative and extreme unused-addend variants with the fix; the original planner fails the addend-16 control (actual Cargo exit 101). The original/packaged dynamic tables are byte-identical and all artifact/manifest hashes are retained. This host metadata replay performs no target mapping or execution and does not admit native frame paths. Signed Docs `214b08666b8b36ad4270bcfee3b3379d8dc08a79` documents the expressions and regenerates only the library's 103-route API reference from exact signed-source rustdoc JSON. All 45 documentation tests, Markdown and canonical checks pass. The full manual has 2,383 pages, 436,424 in-bounds word boxes, zero final warnings and four visually reviewed changed pages. All 3,696 inventoried code/configuration files remain below 1,000 lines; complete semantic authority and private documentation closure remains open. Matching library CI [30](https://git.erikinkinen.fi/erix/lib-dynlink/actions/runs/30)/[31](https://git.erikinkinen.fi/erix/lib-dynlink/actions/runs/31) passes with four complete logs (36,856 bytes), 47 tests per run, strict builds/rustdoc and zero warnings. Docs CI [913](https://git.erikinkinen.fi/erix/docs/actions/runs/913)/[914](https://git.erikinkinen.fi/erix/docs/actions/runs/914) passes with four complete logs (763,872 bytes), 45 tests and 2,383-page renders, zero final warnings. Coherent catalog adoption, complete native source/frame evidence, runnable realms and both full guest build generations remain open. ## Tracking Authority and quality audit: #1. Related native frame work: https://git.erikinkinen.fi/erix/exsh/issues/2 and https://git.erikinkinen.fi/erix/exsh/issues/4. Keep this defect separate from guest timeout and layout-adoption reports. A correction must retain the existing authority and write-range contracts.
Sign in to join this conversation.
No description provided.