Conversation
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head Re-keyed from Measured configuration: a detached worktree of cle at the revision named, this workspace's pinned Python 3.12 environment,
What the third commit does, and what it does not do here. The tests load core dumps written by the kernels they name, added as fixtures by angr/binaries#176, which merged on 2026-08-12, so the fixtures are in
Every Linux x86 cores are unaffected. Fourteen of them, including thread_crash/linux-i386.core ( Caveats:
Hosted CI at head |
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_734 |
529cca7 to
d1d9017
Compare
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS This came out of assembling the angr/vibr preview snapshot (every green open PR merged together, then each component's full test suite run against the result with an With #791 applied, this PR's |
ELF note types are namespaced by the note name: type 1 is a Linux struct elf_prstatus only inside the CORE namespace that Linux uses. ELFCore decoded every NT_PRSTATUS with the Linux layout regardless, so a FreeBSD core raised struct.error when its shorter descriptor ran out, and a NetBSD one was read as a register block when it actually holds a struct netbsd_elfcore_procinfo, which carries no registers at all - those live in a per-LWP note typed with the number of the PT_GETREGS ptrace request. Cores whose process ABI is not the one their ELF header implies, an x32 process dumped by an x86-64 kernel for instance, tripped an assert that python -O strips, leaving registers read at the wrong stride behind. Dispatch on the note name, read FreeBSD struct prstatus and NetBSD per-LWP register notes, and check each descriptor against the layout it is about to be read with. Linux writes the GDT entry note under LINUX rather than under CORE, so look for it there. A thread whose registers cannot be decoded is now dropped with a warning instead of taking the whole load down with it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The regression tests for note dispatch built their own core files with struct.pack. A hand-assembled core only ever has the shape the test author believed the kernel writes, so it can pass while a real FreeBSD, NetBSD or x32 core still fails to load. Load core dumps written by each of those kernels instead, and assert on the register values the dumped process actually held.
d1d9017 to
34a2086
Compare
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Full thread and register report for the eight core dumps in Before — seven of the eight do not load: the FreeBSD and NetBSD notes run off the end of a Linux cle at the merge base, 46a3733After — all eight load with the registers their kernel wrote; the x32 core drops its undecodable thread with a warning and still maps memory: with this change, 34a2086 |
__parse_auxv sized an Elf_auxv_t entry with self.arch.bytes. That is the
instruction set's width, and an auxv entry is two words of the container's
- Elf32_auxv_t for an ELFCLASS32 core and Elf64_auxv_t for an ELFCLASS64
one. The two agree for every core cle has ever loaded, which is why this
has not shown up before.
They stop agreeing for an x32 core, whose ELFCLASS32 container holds
EM_X86_64 code. cle#791 resolves that to AMD64, and reading the
152-byte NT_AUXV of tests/x86_64/elfcore_linux_x32.core at eight bytes
per word runs off the end of the note:
struct.error: unpack_from requires a buffer of at least 160 bytes for
unpacking 8 bytes at offset 152 (actual buffer size is 152)
which fails the whole load, memory mappings included - the same cost this
branch removes for the thread notes. The entries that do fit decode to
nonsense: the first pair reads 0xffd4900000000021 rather than
AT_SYSINFO_EHDR = 0xffd49000.
Take the width from self._reader.elfclass instead. Nothing changes for a
core whose class and machine agree. test_prstatus_abi_mismatch now also
pins three auxv values that only come out right at four bytes, AT_PHENT
= sizeof(Elf32_Phdr) among them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DqcAcuGLrNJViJrpdtFYCS
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Interaction with #791, and the auxv noteThis branch and #791 are each green alone and cannot both be in a rollup: the #791 resolves an ELFCLASS32 container of which costs the caller the whole core, memory mappings included -- exactly what Fix143abf3 takes the width from
Verificationmaster + #791 + this branch, cle's whole suite: The one failure is #791's own Heads: #791 session: sharpen |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
Seven of the eight core dumps in
angr/binarieswritten by a kernel other than plain Linux/x86 do not load at all.tests/x86_64/elfcore_freebsd_amd64.core:and
tests/i386/elfcore_netbsd_i386.coreandtests/x86_64/elfcore_linux_x32.core:One thread note it cannot read costs the caller the whole core, memory mappings included — and that guard is an
assert, whichpython -Ostrips.Root cause
ELFCore.__extract_note_infodispatched on the note type alone:ELF note types are namespaced by the note's name, so a number identifies a struct only together with the kernel that wrote it. FreeBSD's
NT_PRSTATUSis astruct prstatusfromsys/sys/procfs.hsharing no prefix with Linux's; NetBSD's is astruct netbsd_elfcore_procinfoholding no registers at all, its registers living in onePT_GETREGSnote per LWP underNetBSD-CORE@<lwpid>; and Linux writesNT_386_TLSunderLINUX, notCORE, so that branch never fired and cle fell back to guessing the thread pointer out of memory.ELFCoreThreadcompounds it withself.thread_pointer = threadinfo["registers"]["fs_base"], aKeyErroron any kernel that records the segment bases elsewhere.Fix
__parse_auxvtakes an entry's width from the container's ELF class rather than fromself.arch.bytes: anElf_auxv_tis two words of the pointer width, and the two agree for every core whose class and machine agree.Dispatch is keyed on
(n_name, n_type)—CORE,LINUX,FreeBSD, and theNetBSD-CORE@prefix — with per-architecture layouts for FreeBSD'sstruct prstatusand NetBSD's per-LWP register note, and each descriptor is checked against the layout it is about to be read with. A thread whose registers will not decode is dropped with a warning rather than failing the load, and a missingfs_basewarns and yields 0.The x32 core is the deliberate non-recovery: an amd64
elf_prstatusin a file cle reads asX86, so its thread is dropped and its memory still maps. Floating-point and vector register sets are still not read.Testing
tests/test_elfcore.pygains a test per kernel and architecture —test_freebsd_prstatus_amd64,..._i386,..._aarch64,test_netbsd_registers_amd64,..._i386,..._aarch64,test_linux_x86_tls_noteandtest_prstatus_abi_mismatch— asserting the registers the kernel actually wrote,assert registers["rip"] == 0x20242Bamong them. Each loads an unmutated core dump; all eight fail on the merge base. The fixtures are onangr/binariesmaster, added by that repository's PR 176, which merged on 2026-08-12.Validation: #734 (comment)
session: sharpen