Skip to content

Make ELF loading respect program header virtual addresses for non-PIE binaries#1530

Open
cshung wants to merge 1 commit into
hyperlight-dev:mainfrom
cshung:cshung/non-pie-elf-loading
Open

Make ELF loading respect program header virtual addresses for non-PIE binaries#1530
cshung wants to merge 1 commit into
hyperlight-dev:mainfrom
cshung:cshung/non-pie-elf-loading

Conversation

@cshung

@cshung cshung commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Summary

For non-PIE (ET_EXEC) ELF binaries, the guest page table now maps the code region at the ELF's declared virtual address rather than identity-mapping it at the GPA. This allows statically-linked binaries with a fixed load address (e.g., --image-base=0x200000) to execute correctly.

Problem

Previously, Hyperlight assumed code GVA == code GPA (identity mapping). Non-PIE binaries that declare a non-zero base virtual address (via program header p_vaddr) would triple-fault because the guest CPU jumped to the ELF's declared entrypoint VA, which wasn't mapped in the page tables.

Solution

  • Compute code_virt_base from the ELF's lowest LOAD segment p_vaddr
  • For non-PIE (base_va > 0): map code at the declared VA in the guest page tables
  • For PIE (base_va == 0): preserve existing identity mapping behavior (with assertion to guard the invariant)
  • Compute entrypoint as code_virt_base + (entrypoint_va - base_va)

The fix leverages the existing Mapping struct's support for phys_base != virt_base — no changes to the page table code itself.

Testing

  • New non_pie_guest_hello_world integration test exercises full guest lifecycle (init, COW, function call, return value) with a non-PIE simpleguest built at --image-base=0x200000
  • All existing PIE guest tests continue to pass (identity mapping preserved)
  • Tested on Windows/WHP and Linux/KVM

Build infrastructure

  • Added build-rust-guests-non-pie Justfile targets
  • Non-PIE build runs first in guests recipe to avoid clobbering normal guest binaries
  • Added simple_guest_non_pie_as_string() test helper

Contributes to: #1408

Copilot AI review requested due to automatic review settings June 14, 2026 22:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR adds support for running and testing non-PIE Rust guest binaries, including updating snapshot virtual-address mapping so non-PIE guests execute at their declared ELF virtual addresses.

Changes:

  • Add a helper in hyperlight_testing to locate the non-PIE simpleguest binary.
  • Update snapshot mapping/entrypoint calculation to support non-identity VA mappings for non-PIE code regions.
  • Add a new integration test and build automation (Justfile) to produce and run a non-PIE guest.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/hyperlight_testing/src/lib.rs Adds path helper(s) for locating non-PIE Rust guest binaries.
src/hyperlight_host/tests/integration_test.rs Adds an integration test that boots and calls into a non-PIE guest.
src/hyperlight_host/src/sandbox/snapshot/mod.rs Adjusts snapshot mappings and entrypoint VA calculation to support non-PIE guests.
Justfile Adds tasks to build and stage non-PIE Rust guest artifacts.

Comment thread Justfile Outdated
Comment thread src/hyperlight_host/src/sandbox/snapshot/mod.rs
Comment thread src/hyperlight_host/src/sandbox/snapshot/mod.rs Outdated
Comment thread src/hyperlight_testing/src/lib.rs
For non-PIE binaries (ET_EXEC), the page table now maps the code
region at the ELF's declared virtual address rather than identity
mapping at the GPA. The entrypoint is computed correctly as a GVA.

PIE binaries (base_va == 0) continue to use identity mapping,
preserving existing behavior.

Also adds build infrastructure and integration test for non-PIE guests:
- Justfile: build-rust-guests-non-pie target builds simpleguest with
  static relocation model and --image-base=0x200000
- hyperlight_testing: add simple_guest_non_pie_as_string() path helper
- integration_test: non_pie_guest_hello_world exercises full guest
  lifecycle (init, COW, function call) with absolute addresses

Contributes to: hyperlight-dev#1408

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
@cshung cshung force-pushed the cshung/non-pie-elf-loading branch from 7468e06 to 40c43be Compare June 14, 2026 23:10
@cshung

cshung commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

Addressed Copilot review feedback:

  1. Justfile (RUSTFLAGS on Linux) — Fixed. \RUSTFLAGS\ now prefixes \cargo\ directly after \cd &&\ so the env var applies to the build command.

  2. snapshot/mod.rs (virt_base mapping) — No change needed. The code region is a single contiguous block where
    gn.guest_region.start == load_addr\ — there is no offset to lose. The \�ssert_eq!\ is deliberate per codebase convention.

  3. snapshot/mod.rs (entrypoint underflow) — Fixed. Now uses \checked_sub\ with a proper error for malformed ELFs.

  4. lib.rs (doc says 'elf binary') — No change needed. Hyperlight guests are always ELF regardless of host OS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants