Tencent/tinker · warning · IOException
Unable to find .rodata section.
Error message
Unable to find .rodata section.
What it means
ShareOatUtil.getOatFileInstructionSet parses an odex/oat file as ELF (via ShareElfFile) and looks up the section named '.rodata', where the OAT header with the instruction-set string lives. If no section named .rodata exists, it throws IOException('Unable to find .rodata section.'). This happens when the file being parsed is a plain ELF/odex without OAT packaging — e.g. some devices' odex files use different section layouts, or the file is a .so rather than an oat.
Source
Thrown at tinker-android/tinker-android-loader-no-op/src/main/java/com/tencent/tinker/loader/shareutil/ShareOatUtil.java:55
* Get instruction set used to generate {@code oatFile}.
*
* @param oatFile
* the oat file.
* @return
* the instruction used to generate this oat file, if the oat file does not
* contain this value, an empty string will be returned.
*
* @throws IOException
* If anything wrong when parsing the elf format or locating target field in oat header.
*/
public static String getOatFileInstructionSet(File oatFile) throws Throwable {
ShareElfFile elfFile = null;
String result = "";
try {
elfFile = new ShareElfFile(oatFile);
final ShareElfFile.SectionHeader roDataHdr = elfFile.getSectionHeaderByName(".rodata");
if (roDataHdr == null) {
throw new IOException("Unable to find .rodata section.");
}
final FileChannel channel = elfFile.getChannel();
channel.position(roDataHdr.shOffset);
final byte[] oatMagicAndVersion = new byte[8];
ShareElfFile.readUntilLimit(channel, ByteBuffer.wrap(oatMagicAndVersion), "Failed to read oat magic and version.");
if (oatMagicAndVersion[0] != 'o'
|| oatMagicAndVersion[1] != 'a'
|| oatMagicAndVersion[2] != 't'
|| oatMagicAndVersion[3] != '\n') {
throw new IOException(
String.format("Bad oat magic: %x %x %x %x",
oatMagicAndVersion[0],
oatMagicAndVersion[1],
oatMagicAndVersion[2],
oatMagicAndVersion[3])View on GitHub (pinned to 1b7ea02c23)
Solutions
- Call getOatFileInstructionSet defensively and catch Throwable — tinker itself expects IOException here and treats it as 'unknown instruction set'; fall back to Build.SUPPORTED_ABIS / the primary abi.
- Verify the argument is really an odex/oat file (secondary.dex-like path under oat/) before calling.
- On affected ROMs, disable interpret-only mode (useInterpretModeOnSupported32BitSystem = false) so the oat parsing path is avoided.
- Update tinker — newer versions handle more odex layouts.
Example fix
// before
String isa = ShareOatUtil.getOatFileInstructionSet(oatFile); // may throw
// after
String isa;
try {
isa = ShareOatUtil.getOatFileInstructionSet(oatFile);
} catch (Throwable t) {
isa = Build.SUPPORTED_ABIS[0]; // graceful fallback
} Defensive patterns
Strategy: fallback
Validate before calling
if (oatFile == null || !oatFile.getName().endsWith(".odex")
|| !ShareOatUtil.fileLooksLikeOat(oatFile)) {
return Build.SUPPORTED_ABIS[0]; // skip oat parsing entirely
} Type guard
public static boolean looksLikeOat(File f) throws IOException {
try (RandomAccessFile raf = new RandomAccessFile(f, "r")) {
byte[] magic = new byte[4];
raf.seek(0); // .rodata offset unknown pre-parse; at minimum require ELF magic
raf.readFully(magic);
return (magic[0] & 0xff) == 0x7f && magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F';
}
} Try / catch
String isa;
try {
isa = ShareOatUtil.getOatFileInstructionSet(oatFile);
} catch (Throwable t) {
isa = Build.SUPPORTED_ABIS[0]; // some ROM odex layouts lack .rodata
} Prevention
- Wrap oat-parsing calls in try-catch and fall back to SUPPORTED_ABIS
- Disable interpret-only mode on ROMs known to ship odex files without .rodata
- Keep tinker updated for new odex layout handling
When it happens
Trigger: getOatFileInstructionSet(oatFile) invoked on a file that is valid ELF but has no .rodata section — such as a native library passed by mistake, an odex produced by an ART version that strips/renames sections, or an uncompressed check-dex odex variant.
Common situations: Tinker's interpret-mode flow calling this on devices (some Meizu/Huawei ROMs) whose odex layout lacks .rodata; passing a .so path where an oat/odex path was expected; OS version changes to odex format.
Related errors
- Unable to find .rodata section.
- {} Rest bytes insufficient, expect to read {} bytes but only
- bad elf magic: %x %x %x %x.
- Bad oat magic: %x %x %x %x
- Bad oat version: {}
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/045756dd82909dcd.
Report an issue: GitHub.