Skip to content

Read ELF metadata without elftools - #24423

Merged
MikeMcQuaid merged 1 commit into
mainfrom
read-elf-metadata-directly
Nov 1, 2026
Merged

MikeMcQuaid merged 1 commit into
mainfrom
read-elf-metadata-directly

Conversation

@krehel

@krehel krehel commented Nov 1, 2026

Copy link
Copy Markdown
Member
  • ELFShim::Metadata built a PatchELF::Patcher, and so an elftools ELFFile that parses every header through BinData, to read a few fields from the program headers and the dynamic section. Read them with String#unpack instead: the linkage check, relocation and brew bottle read them for every ELF file in a keg.
  • Return exactly what patchelf.rb returned, string encodings included, and leave anything unusual, such as a truncated file, to patchelf.rb as before.
  • Reading metadata no longer loads elftools, BinData and patchelf.rb.

  • Have you followed our Contributing guidelines?
  • Have you checked for other open Pull Requests for the same change?
  • Have you explained what your changes do? Performance claims (e.g. "this is faster") must include brew benchmark results.
  • Have you explained why you'd like these changes included, not just what they do?
  • For bug fixes, have you given step-by-step brew commands to reproduce the bug?
  • Have you written new tests (excluding integration tests)? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) locally?

  • I did not use AI/LLM to create this PR, or I disclosed the tool/model below and reviewed its output; I did not attribute commits to AI and will answer maintainer questions and review comments myself without AI/LLM.

Opus 5.5 xhigh with manual review and testing. The new reader was compared with main's on 3,363 ELF files (arm64 and x86_64 bottles, system libraries and 32-bit and big-endian builds) and on 19,929 truncated or overwritten copies of 1,418 of them: every value, string encoding and exception matched.

Details

Fedora 44 aarch64 VM, hyperfine -N with brew benchmark's environment, bottles cached.

brew linkage util-linux ($(brew --cache)/linkage.json removed before each run, 20 runs)

Command Mean [ms] Min [ms] Max [ms] Relative
main a687be2 351.5 ± 32.1 318.3 449.2 1.55 ± 0.19
branch 226.3 ± 18.0 207.5 264.4 1.00

brew linkage perl ($(brew --cache)/linkage.json removed before each run, 20 runs)

Command Mean [ms] Min [ms] Max [ms] Relative
main a687be2 277.5 ± 29.8 248.6 360.8 1.36 ± 0.15
branch 204.5 ± 4.3 196.1 214.9 1.00

brew install util-linux (one pour, dependencies installed, 10 runs)

Command Mean [s] Min [s] Max [s] Relative
main a687be2 2.211 ± 0.021 2.199 2.268 1.08 ± 0.02
branch 2.042 ± 0.022 2.013 2.070 1.00

brew install python@3.15 (one pour, dependencies installed, 10 runs)

Command Mean [s] Min [s] Max [s] Relative
main a687be2 2.506 ± 0.029 2.467 2.549 1.05 ± 0.02
branch 2.398 ± 0.041 2.352 2.484 1.00

brew install wget (one pour, dependencies installed, 20 runs)

Command Mean [ms] Min [ms] Max [ms] Relative
main a687be2 969.7 ± 12.6 954.9 998.6 1.04 ± 0.02
branch 935.8 ± 9.4 924.6 961.0 1.00

brew install jq wget git tmux htop python3 (39 bottles poured, warm cache, 10 runs)

Command Mean [s] Min [s] Max [s] Relative
main a687be2 22.227 ± 0.150 22.046 22.551 1.02 ± 0.01
branch 21.762 ± 0.120 21.583 21.965 1.00

Reading the metadata of 3,354 ELF files through ELFShim alone takes 2,295 ms on main and 182 ms on the branch (12.6 ± 0.6×). Pours gain less because relocation still rewrites each file through patchelf.rb.

- `ELFShim::Metadata` built a `PatchELF::Patcher`, and so an elftools
  `ELFFile` that parses every header through BinData, to read a few
  fields from the program headers and the dynamic section. Read them
  with `String#unpack` instead: the linkage check, relocation and
  `brew bottle` read them for every ELF file in a keg.
- Return exactly what patchelf.rb returned, string encodings included,
  and leave anything unusual, such as a truncated file, to patchelf.rb
  as before.
- Reading metadata no longer loads elftools, BinData and patchelf.rb.
@coderabbitai

coderabbitai Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f0e784d7-e1c0-42f2-a826-d2d34d3583e5
Commits

Reviewing files that changed from the base of the PR and between 07e4b86 and 032cb6d.

Files selected for processing: 5
  • Library/Homebrew/os/linux/elf.rb
  • Library/Homebrew/test/os/linux/pathname_spec.rb
  • Library/Homebrew/test/support/fixtures/elf/exe_s390x
  • Library/Homebrew/test/support/fixtures/elf/libx_arm32.so.2
  • Library/Homebrew/test/support/fixtures/elf/static_no_phdrs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Summary

Summary by CodeRabbit

  • Improvements
    • ELF metadata can now be read directly across 32-bit and 64-bit files in either byte order, including key library and executable details.
    • Unsupported or incomplete files continue to use the existing fallback reader, while malformed files are handled without returning partial metadata.
    • Files without program headers are now recognised as non-dynamic.

ELFShim::Metadata now reads ELF metadata directly from program headers and the dynamic section. It supports 32-bit and 64-bit files in either byte order, and uses patchelf for unsupported or incomplete input. Specs cover direct reading, fallback cases and files without program headers.

Changes: ELF metadata reading

Layer / File(s) Summary
Direct ELF parsing
Library/Homebrew/os/linux/elf.rb
Adds format constants, a fields structure and a direct reader for ELF headers, program headers and dynamic-section data. Bounded readers handle fields and null-terminated strings.
Fallback selection and validation
Library/Homebrew/os/linux/elf.rb, Library/Homebrew/test/os/linux/pathname_spec.rb
Metadata initialisation selects fields from the direct reader or patchelf. PIE and NODEFLIB checks use local flag constants. Specs cover fallback selection, 32-bit little-endian and 64-bit big-endian files, and files without program headers.
Merge Risk: Minimal · up to 032cb

No actionable issue remains from this review; the PR is ready for normal merge checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly summarises the main change: reading ELF metadata without loading elftools.
Description check Passed The description directly explains the implementation, motivation, compatibility requirements, tests, and benchmark results for the ELF metadata reader.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice, thanks!

@MikeMcQuaid
MikeMcQuaid added this pull request to the merge queue Nov 1, 2026
Merged via the queue into main with commit 184ecd4 Nov 1, 2026
54 checks passed
@MikeMcQuaid
MikeMcQuaid deleted the read-elf-metadata-directly branch November 1, 2026 15:13
@krehel krehel mentioned this pull request Nov 1, 2026
8 tasks done
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

⌂ 换网址