* feat(native): decode Android .note.android.ident ELF notes Decode Android NDK NT_ANDROID_TYPE_IDENT (.note.android.ident, owner Android, type 1) notes in inspect_elf_notes across legacy 4-byte and modern >=132-byte descriptors with bounded TextBudget accounting. * fix(native): isolate Android note scan budget test, scope contract import, and add feature spec * test(native): use domain tool contract in elfNotesMcp boundary test
2.7 KiB
Android .note.android.ident ELF note decoding
Problem and outcome
Android NDK shared libraries and executables linked with Bionic crtbegin_so.o
or crtbrand.S embed an ELF note with owner === "Android" and n_type === 1
(NT_ANDROID_TYPE_IDENT) inside .note.android.ident (SHT_NOTE and/or
PT_NOTE). Legacy Android NDK (< r14) and unbranded platform builds store a
4-byte uint32_t android_api descriptor, while modern NDK (r14+) builds
store a 132-byte (or extended >= 132-byte) descriptor containing
uint32_t android_api (0..4), char ndk_version[64] (4..68), and
char ndk_build_number[64] (68..132).
Previously, inspect_elf_notes / inspect-elf-notes mapped only GNU and
CORE note owners, leaving Android type 1 entries as type_name: "unknown"
with descriptor.hex: null for 132-byte notes (above the 64-byte inline hex
preview ceiling). Extend inspect_elf_notes to decode NT_ANDROID_TYPE_IDENT
into type_name: "android_ident" and a nullable android object across
32-/64-bit and little-/big-endian ELF targets without executing the image.
Requirements
- Map
owner === "Android"andtype === 1totype_name: "android_ident"; otherAndroidnote types remaintype_name: "unknown"withandroid: null, and non-Androidowners keepandroid: null. - Decode 4-byte
NT_ANDROID_TYPE_IDENTdescriptors in the ELF image's byte order as{ android_api, ndk_version: null, ndk_build_number: null }. - Decode
>= 132-byteNT_ANDROID_TYPE_IDENTdescriptors in the ELF image's byte order when both 64-byte fixed slots (4..68and68..132) contain printable ASCII (0x20..0x7e) terminated by0x00and padded solely with0x00through the end of each 64-byte slot. - Degrade truncated (
0..3or5..131bytes), unterminated, control-byte, or non-zero-paddedNT_ANDROID_TYPE_IDENTdescriptors toandroid: nullwhile preserving raw note header fields, descriptor SHA-256, and<= 64-byte hex preview. - Account for fixed-slot scanning (
128bytes cached per descriptor slice inTextBudget.scans) and retainedndk_version/ndk_build_numbertext inTextBudget.usedunder the sharedmax_file_bytesceiling.
Acceptance
Domain, parser, MCP boundary, and CLI/stdio-MCP acceptance tests cover
little-endian ELF64 (aarch64, x86_64) and big-endian ELF32/ELF64 images
across 132-byte, 152-byte extended, and legacy 4-byte descriptors, unknown
Android note types, malformed/truncated/non-ASCII descriptors, and shared
TextBudget scan, scan-cache, and retained-string limits.
Out of scope
Decoding other NT_ANDROID_* note types (such as NT_ANDROID_TYPE_MEMTAG or
NT_ANDROID_TYPE_KUSER), executing target binaries, or invoking external
disassemblers.