参考Java代码
public int Test1(int arg) {
returnaurora.view.AuroraTest.Test2(arg, "testing");
}
Oatdump输出:
2:int com.example.testar.MainActivity.Test1(int) (dex_method_idx=15)
DEX CODE:
0x0000: const-string v0,"testing" // string@1404
0x0002:invoke-static {v2, v0}, int aurora.view.AuroraTest.Test2(int, java.lang.String)//method@6
0x0005: move-result v0
0x0006: return v0
OAT DATA:
frame_size_in_bytes: 48
core_spill_mask: 0x000080e0 (r5, r6, r7,r15)
fp_spill_mask: 0x00000000
vmap_table: 0xb6c5d3fc(offset=0x000313fc)
v0/r5, v2/r6, v65534/r7, v65535/r15
mapping_table: 0xb6c5d3f4(offset=0x000313f4)
gc_map: 0xb6c5d405 (offset=0x00031405)
通IDA查看的指令码:
71 20 06 00 02 00
71操作码
2 参数个数
0006 method idx
02参数V2
00参数 V0
CODE:00008474public int com.example.testar.MainActivity.Test1(
CODE:00008474 int arg)
CODE:00008474 this =v1
CODE:00008474 arg = v2
CODE:00008474 .prologue_end
CODE:00008474 .line 64
CODE:00008474
CODE:00008474 const-string v0, aTesting #"testing"
CODE:00008478 invoke-static {arg, v0}, <int AuroraTest.Test2(int, ref) imp. @ _def_AuroraTest_Test2@IIL>
CODE:0000847E move-result v0
CODE:00008480
CODE:00008480locret:
CODE:00008480 return v0
CODE:00008480Method End
art/runtime/dex_instruction_list.h
134 V(0x71,INVOKE_STATIC, "invoke-static", k35c, false, kMethodRef, kContinue |kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArg) \
135 V(0x72, INVOKE_INTERFACE,"invoke-interface", k35c, false, kMethodRef, kContinue | kThrow |kInvoke, kVerifyRegBMethod | kVerifyVarArg) \
136 V(0x73, RETURN_VOID_BARRIER,"return-void-barrier", k10x, false, kNone, kReturn, kVerifyNone) \
137 V(0x74, INVOKE_VIRTUAL_RANGE,"invoke-virtual/range", k3rc, false, kMethodRef, kContinue | kThrow |kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \
138 V(0x75, INVOKE_SUPER_RANGE,"invoke-super/range", k3rc, false, kMethodRef, kContinue | kThrow |kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \
139 V(0x76, INVOKE_DIRECT_RANGE,"invoke-direct/range", k3rc, false, kMethodRef, kContinue | kThrow |kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \
140 V(0x77,INVOKE_STATIC_RANGE, "invoke-static/range", k3rc, false, kMethodRef,kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \
141 V(0x78, INVOKE_INTERFACE_RANGE,"invoke-interface/range", k3rc, false, kMethodRef, kContinue | kThrow| kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \
art/runtime/interpreter/interpreter.cc
EnterInterpreterFromInvoke -> Execute->ExecuteImpl
2278 case Instruction::INVOKE_STATIC: {
2279 PREAMBLE();
2280 bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst,&result_register);
2281 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
2282 break;
2283 }
2284 case Instruction::INVOKE_STATIC_RANGE: {
2285 PREAMBLE();
2286 bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst,&result_register);
2287 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
2288 break;
2289 }
424static bool DoInvoke(Thread* self, ShadowFrame&shadow_frame,
425 const Instruction* inst,JValue* result) {
426 bool do_assignability_check = do_access_check;
427 uint32_t method_idx = (is_range) ?inst->VRegB_3rc() : inst->VRegB_35c();
428 uint32_t vregC = (is_range) ?inst->VRegC_3rc() : inst->VRegC_35c();
429 Object* receiver = (type == kStatic) ? NULL :shadow_frame.GetVRegReference(vregC);
430 ArtMethod* method = FindMethodFromCode(method_idx, receiver,shadow_frame.GetMethod(), self,
431 do_access_check, type);
432
433 LOG(ERROR) << method->GetDeclaringClass();
434
435 if(UNLIKELY(method == NULL)) {
436 CHECK(self->IsExceptionPending());
437 result->SetJ(0);
438 return false;
439 }else if (UNLIKELY(method->IsAbstract())) {
440 ThrowAbstractMethodError(method);
441 result->SetJ(0);
442 return false;
443 }
476 if (!is_range) {
477 inst->GetArgs(arg);
478 }
230inline uint16_t Instruction::VRegB_35c() const {
231 DCHECK_EQ(FormatOf(Opcode()), k35c);
232 returnFetch16(1);
第二个16为method idx
233}
274inline uint4_t Instruction::VRegC_35c() const {
275 DCHECK_EQ(FormatOf(Opcode()), k35c);
276 returnstatic_cast<uint4_t>(Fetch16(2) & 0x0f);
第3个16位的低4为
277}
284inline void Instruction::GetArgs(uint32_t arg[5]) const {
285 DCHECK_EQ(FormatOf(Opcode()), k35c);
286
287 /*
288 * Note that the fields mentioned in thespec don't appear in
289 * their "usual" positions herecompared to most formats. This
290 * was done so that the field names for theargument count and
291 * reference index match between this formatand the corresponding
292 * range formats (3rc and friends).
293 *
294 * Bottom line: The argument count is alwaysin vA, and the
295 * method constant (or equivalent) is alwaysin vB.
296 */
297 uint16_t regList = Fetch16(2);
298 uint4_t count =InstB(); // This is labeled A in thespec.
299
300 /*
301 * Copy the argument registers into thearg[] array, and
302 * also copy the first argument (if any)into vC. (The
303 * DecodedInstruction structure doesn't haveseparate
304 * fields for {vD, vE, vF, vG}, so there'sno need to make
305 * copies of those.) Note that cases 5..2 fall through.
306 */
307 switch (count) {
308 case 5: arg[4] = InstA();
309 case 4: arg[3] = (regList >> 12)& 0x0f;
310 case 3: arg[2] = (regList >> 8)& 0x0f;
311 case 2: arg[1] = (regList >> 4)& 0x0f;
312 case 1: arg[0] = regList & 0x0f;break;
313 case 0: break; // Valid, but no need to do anything.
314 default:
315 LOG(ERROR) << "Invalid argcount in 35c (" << count << ")";
316 return;
317 }
318}
414 uint4_t InstB() const {
415 return static_cast<uint4_t>(Fetch16(0) >> 12);
20 71
arg count: 2
416 }