运行APP时dex2oat过程中DumpLIRInsn函数出错,段错误SIGSEGV日志如下:
03-17 11:36:58.40321692169 I dex2oat : HXM lir->opcode:-1
03-17 11:36:58.40321692169 I dex2oat : L0x75b3d4cc:
03-17 11:36:58.40421692169 I dex2oat : HXM lir->opcode:-10
03-17 11:36:58.40421692169 I dex2oat : -------- method entry void com.droidhen.api.promptclient.PublisherType.
03-17 11:36:58.40421692169 I dex2oat : HXM lir->opcode:27
03-17 11:36:58.40421692169 I dex2oat : HXM InstName:lw
03-17 11:36:58.40421692169 I dex2oat : HXM BuildInsnString fmt:lw
03-17 11:36:58.40421692169 I dex2oat : HXM BuildInsnString *fmt:l
03-17 11:36:58.40421692169 I dex2oat : HXM BuildInsnString *fmt:w
03-17 11:36:58.40521692169 I dex2oat : HXM InstFmt:!0r,!1d(!2r)
03-17 11:36:58.40521692169 I dex2oat : HXM BuildInsnString fmt:!0r,!1d(!2r)
03-17 11:36:58.40521692169 I dex2oat : HXM BuildInsnString *fmt:!
03-17 11:36:58.40521692169 I dex2oat : HXM BuildInsnString nc:0
03-17 11:36:58.40521692169 I dex2oat : HXM BuildInsnString 0:130 1:128 2:145 3:0 4:0
03-17 11:36:58.40521692169 I dex2oat : HXM BuildInsnString switch *fmt:r operand:130
03-17 11:36:58.40521692169 F libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 2169 (main)
03-17 11:36:58.52010871087 I DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
.........
03-17 11:36:58.54910871087 I DEBUG: backtrace:
03-17 11:36:58.54910871087 E DEBUG: AM write failure (32 / Broken pipe)
03-17 11:36:58.54910871087 I DEBUG:#00 pc 0002276c/system/lib/libc.so (strlen+64)
03-17 11:36:58.54910871087 I DEBUG:#01 pc 0019bab8/system/lib/libart-compiler.so (art::MipsMir2Lir::BuildInsnString(char const*, art::LIR*, unsigned char*)+2036)
03-17 11:36:58.54910871087 I DEBUG:#02 pc 0015e684/system/lib/libart-compiler.so (art::Mir2Lir::DumpLIRInsn(art::LIR*, unsigned char*)+2600)
03-17 11:36:58.54910871087 I DEBUG:#03 pc 0015f068/system/lib/libart-compiler.so (art::Mir2Lir::CodegenDump()+1540)
03-17 11:36:58.54910871087 I DEBUG:#04 pc 001b4ec4/system/lib/libart-compiler.so (art::QuickCompiler::Compile(art::DexFile::CodeItem const*, unsigned int, art::InvokeType, unsigned short, unsigned int, _jobject*, art::DexFile const&) const+2888)
03-17 11:36:58.54910871087 I DEBUG:#05 pc 0025e7b0/system/lib/libart-compiler.so (art::CompilerDriver::CompileMethod(art::Thread*, art::DexFile::CodeItem const*, unsigned int, art::InvokeType, unsigned short, unsigned int, _jobject*, art::DexFile const&, art::DexToDexCompilationLevel, bool)+3080)
03-17 11:36:58.54910871087 I DEBUG:#06 pc 0025fdd4/system/lib/libart-compiler.so (art::CompilerDriver::CompileClass(art::ParallelCompilationManager const*, unsigned int)+3404)
03-17 11:36:58.54910871087 I DEBUG:#07 pc 0024c520/system/lib/libart-compiler.so
03-17 11:36:58.54910871087 I DEBUG:#08 pc 004c8da4/system/lib/libart.so (art::ThreadPool::Wait(art::Thread*, bool, bool)+336)
03-17 11:36:58.55010871087 I DEBUG:#09 pc 00254044/system/lib/libart-compiler.so
03-17 11:36:58.55010871087 I DEBUG:#10 pc 00269100/system/lib/libart-compiler.so (art::CompilerDriver::Compile(_jobject*, std::__1::vector > const&, art::ThreadPool*, art::TimingLogger*)+236)
03-17 11:36:58.55010871087 I DEBUG:#11 pc 0026aa98/system/lib/libart-compiler.so (art::CompilerDriver::CompileAll(_jobject*, std::__1::vector > const&, art::TimingLogger*)+224)
03-17 11:36:58.55010871087 I DEBUG:#12 pc 000110a8/system/bin/dex2oat
03-17 11:36:58.55010871087 I DEBUG:#13 pc 0001ced0/system/bin/dex2oat
03-17 11:36:58.55010871087 I DEBUG:#14 pc 00007d00/system/bin/dex2oat (main+40)
03-17 11:36:58.55010871087 I DEBUG:#15 pc 000143b8/system/lib/libc.so (__libc_init+140)
03-17 11:36:58.55010871087 I DEBUG:#16 pc 00007e74/system/bin/dex2oat
03-17 11:36:58.55010871087 I DEBUG:#17 pc 00007e1c/system/bin/dex2oat (__start+44)
经追踪,是在函数BuildInsnString(...) 中解析指令 lw 的操作数!0r , !1d(!2r)时, switch语句中case ‘r'分支中的
DCHECK(operand>=0 && operand < MIPS_REG_COUNT);
出错,打印出operand的值为130,打印出所有LIR的operand[0],其值都位于128(128 + 0)到159(128 + 31)之间。
继续向上追踪operand[ 0 ]是在何处被赋值的,函数调用关系如下:
Materialize() --> MethodMIR2LIR() --> MethodBlockCodeGen(...) --> MipsMir2Lir::GenEntrySequence(...) -->
Load32Disp(rs_rMIPS_SELF, Thread::StackEndOffset<4>().Int32Value(), check_reg) (其中 check_reg 和 rs_rMIPS_SELF 为寄存器,其operand[0] 分别为 0x8082 (0x8000 | 0x0080 | 0x0002(2号寄存器)) 和 0x8091( 0x8000 | 0x0080 | 0x0011 (17号寄存器))-->
Load32Disp(...) --> MipsMir2Lir::LoadBaseDispBody(...)--> NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg()) --> RawLIR(...) ,
其中函数GetReg()实现如下:
int GetReg() const {
DCHECK(!IsPair()) << "reg_ = 0x" << std::hex << reg_;
return Valid() ? (reg_ & kRegValMask) : kInvalidRegVal;
}
kRegValMask为 & 0x03ff, 返回值并非寄存器号,而是0x0080 | 0x0002 = 130 和 0x0080 | 0x0011 = 145 .
最后,在 switch语句中case ‘r'分支中的 DCHECK(operand>=0 && operand < MIPS_REG_COUNT);
之前添加如下语句,解决了问题。
operand = RegStorage::RegNum(operand);