{"record":{"id":"97c91448e2cb3bca","repo":"Tencent/tinker","slug":"bad-elf-magic-x-x-x-x-97c914","errorCode":null,"errorMessage":"bad elf magic: %x %x %x %x.","messagePattern":"bad elf magic: %x %x %x %x\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareElfFile.java","lineNumber":213,"sourceCode":"        public final short eType;\n        public final short eMachine;\n        public final int eVersion;\n        public final long eEntry;\n        public final long ePhOff;\n        public final long eShOff;\n        public final int eFlags;\n        public final short eEhSize;\n        public final short ePhEntSize;\n        public final short ePhNum;\n        public final short eShEntSize;\n        public final short eShNum;\n        public final short eShStrNdx;\n\n        private ElfHeader(FileChannel channel) throws IOException {\n            channel.position(0);\n            channel.read(ByteBuffer.wrap(eIndent));\n            if (eIndent[0] != 0x7F || eIndent[1] != 'E' || eIndent[2] != 'L' || eIndent[3] != 'F') {\n                throw new IOException(String.format(\"bad elf magic: %x %x %x %x.\", eIndent[0], eIndent[1], eIndent[2], eIndent[3]));\n            }\n\n            assertInRange(eIndent[EI_CLASS], ELFCLASS32, ELFCLASS64, \"bad elf class: \" + eIndent[EI_CLASS]);\n            assertInRange(eIndent[EI_DATA], ELFDATA2LSB, ELFDATA2MSB, \"bad elf data encoding: \" + eIndent[EI_DATA]);\n\n            final ByteBuffer restBuffer = ByteBuffer.allocate(eIndent[EI_CLASS] == ELFCLASS32 ? 36 : 48);\n            restBuffer.order(eIndent[EI_DATA] == ELFDATA2LSB ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);\n            readUntilLimit(channel, restBuffer, \"failed to read rest part of ehdr.\");\n\n            eType = restBuffer.getShort();\n            eMachine = restBuffer.getShort();\n\n            eVersion = restBuffer.getInt();\n            assertInRange(eVersion, EV_CURRENT, EV_CURRENT, \"bad elf version: \" + eVersion);\n\n            switch (eIndent[EI_CLASS]) {\n                case ELFCLASS32:\n                    eEntry = restBuffer.getInt();","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareElfFile.java#L195-L231","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the file starts with 0x7F 'ELF' (file command or a 4-byte check) before handing it to ShareElfFile.","Ensure you point at the real odex location (/oat/<isa>/xxx.odex) and that it exists with size > 0 before parsing.","If the odex is missing or malformed, skip the oat instruction-set probing and fall back to a different way of obtaining the ISA.","Regenerate the odex (run the app once so dexopt completes) before applying or verifying patches."],"exampleFix":"// before\nelfFile = new ShareElfFile(oatFile);\n// after\nif (!SharePatchFileUtil.isLegalFile(oatFile) || oatFile.length() < 16) {\n    throw new IOException(\"odex missing or too small: \" + oatFile);\n}\nelfFile = new ShareElfFile(oatFile);","handlingStrategy":"validation","validationCode":"// Check ELF magic before parsing\ntry (RandomAccessFile raf = new RandomAccessFile(file, \"r\")) {\n    int b0 = raf.read(), b1 = raf.read(), b2 = raf.read(), b3 = raf.read();\n    if (b0 != 0x7F || b1 != 'E' || b2 != 'L' || b3 != 'F') {\n        // not an ELF: do not hand to ShareElfFile\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    ShareElfFile elf = new ShareElfFile(file);\n} catch (IOException e) {\n    // message starts with 'bad elf magic': wrong file type supplied\n}","preventionTips":["Always derive the odex path via optimizedPathFor rather than guessing file paths.","Ensure the odex exists and is non-empty before oat parsing.","Run the app once after install/OTA so dexopt completes before patching."],"tags":["android","tinker","elf","oat","file-format"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}