701 lines
26 KiB
C++
701 lines
26 KiB
C++
/*
|
|
* Copyright (C) 2008 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/*
|
|
* Dalvik instruction utility functions.
|
|
*
|
|
* IMPORTANT NOTE: Much of the contents of this file are generated
|
|
* automatically by the opcode-gen tool. Any edits to the generated
|
|
* sections will get wiped out the next time the tool is run.
|
|
*/
|
|
|
|
#include "InstrUtils.h"
|
|
#include <stdlib.h>
|
|
|
|
/*
|
|
* Table that maps each opcode to the full width of instructions that
|
|
* use that opcode, in (16-bit) code units. Unimplemented opcodes as
|
|
* well as the "breakpoint" opcode have a width of zero.
|
|
*/
|
|
static InstructionWidth gInstructionWidthTable[kNumPackedOpcodes] = {
|
|
// BEGIN(libdex-widths); GENERATED AUTOMATICALLY BY opcode-gen
|
|
1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 2, 3, 2, 2, 3, 5, 2, 2, 3, 2, 1, 1, 2,
|
|
2, 1, 2, 2, 3, 3, 3, 1, 1, 2, 3, 3, 3, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
|
|
0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3,
|
|
3, 3, 3, 0, 3, 3, 3, 3, 3, 0, 0, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 3, 3,
|
|
3, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 3, 3, 2, 0,
|
|
// END(libdex-widths)
|
|
};
|
|
|
|
/*
|
|
* Table that maps each opcode to the flags associated with that
|
|
* opcode.
|
|
*/
|
|
static u1 gOpcodeFlagsTable[kNumPackedOpcodes] = {
|
|
// BEGIN(libdex-flags); GENERATED AUTOMATICALLY BY opcode-gen
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanReturn,
|
|
kInstrCanReturn,
|
|
kInstrCanReturn,
|
|
kInstrCanReturn,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue,
|
|
kInstrCanThrow,
|
|
kInstrCanBranch,
|
|
kInstrCanBranch,
|
|
kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanSwitch,
|
|
kInstrCanContinue|kInstrCanSwitch,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
kInstrCanContinue|kInstrCanBranch,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
0,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
0,
|
|
0,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
0,
|
|
kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanReturn,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
|
|
kInstrCanContinue|kInstrCanThrow,
|
|
0,
|
|
// END(libdex-flags)
|
|
};
|
|
|
|
/*
|
|
* Table that maps each opcode to the instruction format associated
|
|
* that opcode.
|
|
*/
|
|
static u1 gInstructionFormatTable[kNumPackedOpcodes] = {
|
|
// BEGIN(libdex-formats); GENERATED AUTOMATICALLY BY opcode-gen
|
|
kFmt10x, kFmt12x, kFmt22x, kFmt32x, kFmt12x, kFmt22x, kFmt32x,
|
|
kFmt12x, kFmt22x, kFmt32x, kFmt11x, kFmt11x, kFmt11x, kFmt11x,
|
|
kFmt10x, kFmt11x, kFmt11x, kFmt11x, kFmt11n, kFmt21s, kFmt31i,
|
|
kFmt21h, kFmt21s, kFmt31i, kFmt51l, kFmt21h, kFmt21c, kFmt31c,
|
|
kFmt21c, kFmt11x, kFmt11x, kFmt21c, kFmt22c, kFmt12x, kFmt21c,
|
|
kFmt22c, kFmt35c, kFmt3rc, kFmt31t, kFmt11x, kFmt10t, kFmt20t,
|
|
kFmt30t, kFmt31t, kFmt31t, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
|
|
kFmt23x, kFmt22t, kFmt22t, kFmt22t, kFmt22t, kFmt22t, kFmt22t,
|
|
kFmt21t, kFmt21t, kFmt21t, kFmt21t, kFmt21t, kFmt21t, kFmt00x,
|
|
kFmt00x, kFmt00x, kFmt00x, kFmt00x, kFmt00x, kFmt23x, kFmt23x,
|
|
kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
|
|
kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt22c, kFmt22c,
|
|
kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c,
|
|
kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt21c, kFmt21c,
|
|
kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c,
|
|
kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt35c, kFmt35c,
|
|
kFmt35c, kFmt35c, kFmt35c, kFmt00x, kFmt3rc, kFmt3rc, kFmt3rc,
|
|
kFmt3rc, kFmt3rc, kFmt00x, kFmt00x, kFmt12x, kFmt12x, kFmt12x,
|
|
kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
|
|
kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
|
|
kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt23x, kFmt23x, kFmt23x,
|
|
kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
|
|
kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
|
|
kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
|
|
kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
|
|
kFmt23x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
|
|
kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
|
|
kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
|
|
kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
|
|
kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt22s, kFmt22s,
|
|
kFmt22s, kFmt22s, kFmt22s, kFmt22s, kFmt22s, kFmt22s, kFmt22b,
|
|
kFmt22b, kFmt22b, kFmt22b, kFmt22b, kFmt22b, kFmt22b, kFmt22b,
|
|
kFmt22b, kFmt22b, kFmt22b, kFmt22c, kFmt22c, kFmt21c, kFmt21c,
|
|
kFmt22c, kFmt22c, kFmt22c, kFmt21c, kFmt21c, kFmt00x, kFmt20bc,
|
|
kFmt35mi, kFmt3rmi, kFmt35c, kFmt10x, kFmt22cs, kFmt22cs, kFmt22cs,
|
|
kFmt22cs, kFmt22cs, kFmt22cs, kFmt35ms, kFmt3rms, kFmt45cc, kFmt4rcc,
|
|
kFmt35c, kFmt3rc, kFmt21c, kFmt00x,
|
|
// END(libdex-formats)
|
|
};
|
|
|
|
/*
|
|
* Table that maps each opcode to the index type implied by that
|
|
* opcode.
|
|
*/
|
|
static u1 gInstructionIndexTypeTable[kNumPackedOpcodes] = {
|
|
// BEGIN(libdex-index-types); GENERATED AUTOMATICALLY BY opcode-gen
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexStringRef,
|
|
kIndexStringRef, kIndexTypeRef, kIndexNone,
|
|
kIndexNone, kIndexTypeRef, kIndexTypeRef,
|
|
kIndexNone, kIndexTypeRef, kIndexTypeRef,
|
|
kIndexTypeRef, kIndexTypeRef, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexUnknown,
|
|
kIndexUnknown, kIndexUnknown, kIndexUnknown,
|
|
kIndexUnknown, kIndexUnknown, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexMethodRef,
|
|
kIndexMethodRef, kIndexMethodRef, kIndexMethodRef,
|
|
kIndexMethodRef, kIndexUnknown, kIndexMethodRef,
|
|
kIndexMethodRef, kIndexMethodRef, kIndexMethodRef,
|
|
kIndexMethodRef, kIndexUnknown, kIndexUnknown,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexNone,
|
|
kIndexNone, kIndexNone, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
|
|
kIndexFieldRef, kIndexFieldRef, kIndexUnknown,
|
|
kIndexVaries, kIndexInlineMethod, kIndexInlineMethod,
|
|
kIndexMethodRef, kIndexNone, kIndexFieldOffset,
|
|
kIndexFieldOffset, kIndexFieldOffset, kIndexFieldOffset,
|
|
kIndexFieldOffset, kIndexFieldOffset, kIndexVtableOffset,
|
|
kIndexVtableOffset, kIndexMethodAndProtoRef, kIndexMethodAndProtoRef,
|
|
kCallSiteRef, kCallSiteRef, kIndexFieldRef,
|
|
kIndexUnknown,
|
|
// END(libdex-index-types)
|
|
};
|
|
|
|
/*
|
|
* Global InstructionInfoTables struct.
|
|
*/
|
|
InstructionInfoTables gDexOpcodeInfo = {
|
|
gInstructionFormatTable,
|
|
gInstructionIndexTypeTable,
|
|
gOpcodeFlagsTable,
|
|
gInstructionWidthTable
|
|
};
|
|
|
|
/*
|
|
* Handy macros for helping decode instructions.
|
|
*/
|
|
#define FETCH(_offset) (insns[(_offset)])
|
|
#define FETCH_u4(_offset) (fetch_u4_impl((_offset), insns))
|
|
#define INST_A(_inst) (((u2)(_inst) >> 8) & 0x0f)
|
|
#define INST_B(_inst) ((u2)(_inst) >> 12)
|
|
#define INST_AA(_inst) ((_inst) >> 8)
|
|
|
|
/* Helper for FETCH_u4, above. */
|
|
static inline u4 fetch_u4_impl(u4 offset, const u2* insns) {
|
|
return insns[offset] | ((u4) insns[offset+1] << 16);
|
|
}
|
|
|
|
/*
|
|
* Decode the instruction pointed to by "insns".
|
|
*
|
|
* Fills out the pieces of "pDec" that are affected by the current
|
|
* instruction. Does not touch anything else.
|
|
*/
|
|
void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec)
|
|
{
|
|
u2 inst = *insns;
|
|
Opcode opcode = dexOpcodeFromCodeUnit(inst);
|
|
InstructionFormat format = dexGetFormatFromOpcode(opcode);
|
|
|
|
pDec->opcode = opcode;
|
|
pDec->indexType = dexGetIndexTypeFromOpcode(opcode);
|
|
|
|
switch (format) {
|
|
case kFmt10x: // op
|
|
/* nothing to do; copy the AA bits out for the verifier */
|
|
pDec->vA = INST_AA(inst);
|
|
break;
|
|
case kFmt12x: // op vA, vB
|
|
pDec->vA = INST_A(inst);
|
|
pDec->vB = INST_B(inst);
|
|
break;
|
|
case kFmt11n: // op vA, #+B
|
|
pDec->vA = INST_A(inst);
|
|
pDec->vB = (s4) (INST_B(inst) << 28) >> 28; // sign extend 4-bit value
|
|
break;
|
|
case kFmt11x: // op vAA
|
|
pDec->vA = INST_AA(inst);
|
|
break;
|
|
case kFmt10t: // op +AA
|
|
pDec->vA = (s1) INST_AA(inst); // sign-extend 8-bit value
|
|
break;
|
|
case kFmt20t: // op +AAAA
|
|
pDec->vA = (s2) FETCH(1); // sign-extend 16-bit value
|
|
break;
|
|
case kFmt20bc: // [opt] op AA, thing@BBBB
|
|
case kFmt21c: // op vAA, thing@BBBB
|
|
case kFmt22x: // op vAA, vBBBB
|
|
pDec->vA = INST_AA(inst);
|
|
pDec->vB = FETCH(1);
|
|
break;
|
|
case kFmt21s: // op vAA, #+BBBB
|
|
case kFmt21t: // op vAA, +BBBB
|
|
pDec->vA = INST_AA(inst);
|
|
pDec->vB = (s2) FETCH(1); // sign-extend 16-bit value
|
|
break;
|
|
case kFmt21h: // op vAA, #+BBBB0000[00000000]
|
|
pDec->vA = INST_AA(inst);
|
|
/*
|
|
* The value should be treated as right-zero-extended, but we don't
|
|
* actually do that here. Among other things, we don't know if it's
|
|
* the top bits of a 32- or 64-bit value.
|
|
*/
|
|
pDec->vB = FETCH(1);
|
|
break;
|
|
case kFmt23x: // op vAA, vBB, vCC
|
|
pDec->vA = INST_AA(inst);
|
|
pDec->vB = FETCH(1) & 0xff;
|
|
pDec->vC = FETCH(1) >> 8;
|
|
break;
|
|
case kFmt22b: // op vAA, vBB, #+CC
|
|
pDec->vA = INST_AA(inst);
|
|
pDec->vB = FETCH(1) & 0xff;
|
|
pDec->vC = (s1) (FETCH(1) >> 8); // sign-extend 8-bit value
|
|
break;
|
|
case kFmt22s: // op vA, vB, #+CCCC
|
|
case kFmt22t: // op vA, vB, +CCCC
|
|
pDec->vA = INST_A(inst);
|
|
pDec->vB = INST_B(inst);
|
|
pDec->vC = (s2) FETCH(1); // sign-extend 16-bit value
|
|
break;
|
|
case kFmt22c: // op vA, vB, thing@CCCC
|
|
case kFmt22cs: // [opt] op vA, vB, field offset CCCC
|
|
pDec->vA = INST_A(inst);
|
|
pDec->vB = INST_B(inst);
|
|
pDec->vC = FETCH(1);
|
|
break;
|
|
case kFmt30t: // op +AAAAAAAA
|
|
pDec->vA = FETCH_u4(1); // signed 32-bit value
|
|
break;
|
|
case kFmt31t: // op vAA, +BBBBBBBB
|
|
case kFmt31c: // op vAA, string@BBBBBBBB
|
|
pDec->vA = INST_AA(inst);
|
|
pDec->vB = FETCH_u4(1); // 32-bit value
|
|
break;
|
|
case kFmt32x: // op vAAAA, vBBBB
|
|
pDec->vA = FETCH(1);
|
|
pDec->vB = FETCH(2);
|
|
break;
|
|
case kFmt31i: // op vAA, #+BBBBBBBB
|
|
pDec->vA = INST_AA(inst);
|
|
pDec->vB = FETCH_u4(1); // signed 32-bit value
|
|
break;
|
|
case kFmt35c: // op {vC, vD, vE, vF, vG}, thing@BBBB
|
|
case kFmt35ms: // [opt] invoke-virtual+super
|
|
case kFmt35mi: // [opt] inline invoke
|
|
{
|
|
/*
|
|
* Note that the fields mentioned in the spec don't appear in
|
|
* their "usual" positions here compared to most formats. This
|
|
* was done so that the field names for the argument count and
|
|
* reference index match between this format and the corresponding
|
|
* range formats (3rc and friends).
|
|
*
|
|
* Bottom line: The argument count is always in vA, and the
|
|
* method constant (or equivalent) is always in vB.
|
|
*/
|
|
u2 regList;
|
|
int i, count;
|
|
|
|
pDec->vA = INST_B(inst); // This is labeled A in the spec.
|
|
pDec->vB = FETCH(1);
|
|
regList = FETCH(2);
|
|
|
|
count = pDec->vA;
|
|
|
|
/*
|
|
* Copy the argument registers into the arg[] array, and
|
|
* also copy the first argument (if any) into vC. (The
|
|
* DecodedInstruction structure doesn't have separate
|
|
* fields for {vD, vE, vF, vG}, so there's no need to make
|
|
* copies of those.) Note that cases 5..2 fall through.
|
|
*/
|
|
switch (count) {
|
|
case 5: {
|
|
if (format == kFmt35mi) {
|
|
/* A fifth arg is verboten for inline invokes. */
|
|
ALOGW("Invalid arg count in 35mi (5)");
|
|
goto bail;
|
|
}
|
|
/*
|
|
* Per note at the top of this format decoder, the
|
|
* fifth argument comes from the A field in the
|
|
* instruction, but it's labeled G in the spec.
|
|
*/
|
|
pDec->arg[4] = INST_A(inst);
|
|
}
|
|
case 4: pDec->arg[3] = (regList >> 12) & 0x0f;
|
|
case 3: pDec->arg[2] = (regList >> 8) & 0x0f;
|
|
case 2: pDec->arg[1] = (regList >> 4) & 0x0f;
|
|
case 1: pDec->vC = pDec->arg[0] = regList & 0x0f; break;
|
|
case 0: break; // Valid, but no need to do anything.
|
|
default:
|
|
ALOGW("Invalid arg count in 35c/35ms/35mi (%d)", count);
|
|
goto bail;
|
|
}
|
|
}
|
|
break;
|
|
case kFmt3rc: // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
|
|
case kFmt3rms: // [opt] invoke-virtual+super/range
|
|
case kFmt3rmi: // [opt] execute-inline/range
|
|
pDec->vA = INST_AA(inst);
|
|
pDec->vB = FETCH(1);
|
|
pDec->vC = FETCH(2);
|
|
break;
|
|
case kFmt51l: // op vAA, #+BBBBBBBBBBBBBBBB
|
|
pDec->vA = INST_AA(inst);
|
|
pDec->vB_wide = FETCH_u4(1) | ((u8) FETCH_u4(3) << 32);
|
|
break;
|
|
case kFmt45cc:
|
|
{
|
|
// AG op BBBB FEDC HHHH
|
|
pDec->vA = INST_B(inst); // This is labelled A in the spec.
|
|
pDec->vB = FETCH(1); // vB meth@BBBB
|
|
u2 fedc = FETCH(2);
|
|
pDec->vC = fedc & 0xf;
|
|
pDec->arg[0] = (fedc >> 4) & 0xf; // vD
|
|
pDec->arg[1] = (fedc >> 8) & 0xf; // vE
|
|
pDec->arg[2] = (fedc >> 12); // vF
|
|
pDec->arg[3] = INST_A(inst); // vG
|
|
pDec->arg[4] = FETCH(3); // vH proto@HHHH
|
|
}
|
|
break;
|
|
case kFmt4rcc:
|
|
{
|
|
// AA op BBBB CCCC HHHH
|
|
pDec->vA = INST_AA(inst);
|
|
pDec->vB = FETCH(1);
|
|
pDec->vC = FETCH(2);
|
|
pDec->arg[4] = FETCH(3); // vH proto@HHHH
|
|
}
|
|
break;
|
|
default:
|
|
ALOGW("Can't decode unexpected format %d (op=%d)", format, opcode);
|
|
assert(false);
|
|
break;
|
|
}
|
|
|
|
bail:
|
|
;
|
|
}
|
|
|
|
/*
|
|
* Return the width of the specified instruction, or 0 if not defined. Also
|
|
* works for special OP_NOP entries, including switch statement data tables
|
|
* and array data.
|
|
*/
|
|
size_t dexGetWidthFromInstruction(const u2* insns)
|
|
{
|
|
size_t width;
|
|
|
|
if (*insns == kPackedSwitchSignature) {
|
|
width = 4 + insns[1] * 2;
|
|
} else if (*insns == kSparseSwitchSignature) {
|
|
width = 2 + insns[1] * 4;
|
|
} else if (*insns == kArrayDataSignature) {
|
|
u2 elemWidth = insns[1];
|
|
u4 len = insns[2] | (((u4)insns[3]) << 16);
|
|
// The plus 1 is to round up for odd size and width.
|
|
width = 4 + (elemWidth * len + 1) / 2;
|
|
} else {
|
|
width = dexGetWidthFromOpcode(dexOpcodeFromCodeUnit(insns[0]));
|
|
}
|
|
|
|
return width;
|
|
}
|