Tencent/tinker · error · IOException

bad elf magic: %x %x %x %x.

Error message

bad elf magic: %x %x %x %x.

What it means

While parsing the ELF header of an odex/oat/so file, ShareElfFile checks that the first four identification bytes are 0x7F 'E' 'L' 'F'. If not, it throws IOException("bad elf magic: %x %x %x %x.") printing the offending bytes. The file is simply not an ELF binary.

Source

Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareElfFile.java:213

        public final short eType;
        public final short eMachine;
        public final int eVersion;
        public final long eEntry;
        public final long ePhOff;
        public final long eShOff;
        public final int eFlags;
        public final short eEhSize;
        public final short ePhEntSize;
        public final short ePhNum;
        public final short eShEntSize;
        public final short eShNum;
        public final short eShStrNdx;

        private ElfHeader(FileChannel channel) throws IOException {
            channel.position(0);
            channel.read(ByteBuffer.wrap(eIndent));
            if (eIndent[0] != 0x7F || eIndent[1] != 'E' || eIndent[2] != 'L' || eIndent[3] != 'F') {
                throw new IOException(String.format("bad elf magic: %x %x %x %x.", eIndent[0], eIndent[1], eIndent[2], eIndent[3]));
            }

            assertInRange(eIndent[EI_CLASS], ELFCLASS32, ELFCLASS64, "bad elf class: " + eIndent[EI_CLASS]);
            assertInRange(eIndent[EI_DATA], ELFDATA2LSB, ELFDATA2MSB, "bad elf data encoding: " + eIndent[EI_DATA]);

            final ByteBuffer restBuffer = ByteBuffer.allocate(eIndent[EI_CLASS] == ELFCLASS32 ? 36 : 48);
            restBuffer.order(eIndent[EI_DATA] == ELFDATA2LSB ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
            readUntilLimit(channel, restBuffer, "failed to read rest part of ehdr.");

            eType = restBuffer.getShort();
            eMachine = restBuffer.getShort();

            eVersion = restBuffer.getInt();
            assertInRange(eVersion, EV_CURRENT, EV_CURRENT, "bad elf version: " + eVersion);

            switch (eIndent[EI_CLASS]) {
                case ELFCLASS32:
                    eEntry = restBuffer.getInt();

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Verify the file starts with 0x7F 'ELF' (file command or a 4-byte check) before handing it to ShareElfFile.
  2. Ensure you point at the real odex location (/oat/<isa>/xxx.odex) and that it exists with size > 0 before parsing.
  3. If the odex is missing or malformed, skip the oat instruction-set probing and fall back to a different way of obtaining the ISA.
  4. Regenerate the odex (run the app once so dexopt completes) before applying or verifying patches.

Example fix

// before
elfFile = new ShareElfFile(oatFile);
// after
if (!SharePatchFileUtil.isLegalFile(oatFile) || oatFile.length() < 16) {
    throw new IOException("odex missing or too small: " + oatFile);
}
elfFile = new ShareElfFile(oatFile);
Defensive patterns

Strategy: validation

Validate before calling

// Check ELF magic before parsing
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
    int b0 = raf.read(), b1 = raf.read(), b2 = raf.read(), b3 = raf.read();
    if (b0 != 0x7F || b1 != 'E' || b2 != 'L' || b3 != 'F') {
        // not an ELF: do not hand to ShareElfFile
    }
}

Try / catch

try {
    ShareElfFile elf = new ShareElfFile(file);
} catch (IOException e) {
    // message starts with 'bad elf magic': wrong file type supplied
}

Prevention

When it happens

Trigger: new ShareElfFile(file) (directly or via ShareOatUtil.getOatFileInstructionSet) on a file whose first 4 bytes are not the ELF magic — e.g. a raw dex, zip, or empty file passed where an odex/oat was expected.

Common situations: Passing a .dex path instead of the derived .odex path on Android O+; the odex file not yet generated when the check runs; an art file from an unexpected ART version with a different container format; a zero-length file created by a failed earlier step.

Related errors


AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14). Data as JSON: /api/errors/97c91448e2cb3bca. Report an issue: GitHub.