#include <stdint.h>
#include <deque>
#include <string>
#include <vector>
#include <android-base/stringprintf.h>
#include <unwindstack/DwarfError.h>
#include <unwindstack/DwarfMemory.h>
#include <unwindstack/Log.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
#include "DwarfOp.h"
namespace unwindstack {
enum DwarfOpHandleFunc : uint8_t {
OP_ILLEGAL = 0,
OP_DEREF,
OP_DEREF_SIZE,
OP_PUSH,
OP_DUP,
OP_DROP,
OP_OVER,
OP_PICK,
OP_SWAP,
OP_ROT,
OP_ABS,
OP_AND,
OP_DIV,
OP_MINUS,
OP_MOD,
OP_MUL,
OP_NEG,
OP_NOT,
OP_OR,
OP_PLUS,
OP_PLUS_UCONST,
OP_SHL,
OP_SHR,
OP_SHRA,
OP_XOR,
OP_BRA,
OP_EQ,
OP_GE,
OP_GT,
OP_LE,
OP_LT,
OP_NE,
OP_SKIP,
OP_LIT,
OP_REG,
OP_REGX,
OP_BREG,
OP_BREGX,
OP_NOP,
OP_NOT_IMPLEMENTED,
};
struct OpCallback {
const char name[26];
DwarfOpHandleFunc handle_func;
uint8_t num_required_stack_values;
uint8_t num_operands;
uint8_t operands[2];
};
constexpr static OpCallback kCallbackTable[256] = {
{"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {
"DW_OP_addr",
OP_PUSH,
0,
1,
{DW_EH_PE_absptr},
},
{"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {
"DW_OP_deref",
OP_DEREF,
1,
0,
{},
},
{"", OP_ILLEGAL, 0, 0, {}}, {
"DW_OP_const1u",
OP_PUSH,
0,
1,
{DW_EH_PE_udata1},
},
{
"DW_OP_const1s",
OP_PUSH,
0,
1,
{DW_EH_PE_sdata1},
},
{
"DW_OP_const2u",
OP_PUSH,
0,
1,
{DW_EH_PE_udata2},
},
{
"DW_OP_const2s",
OP_PUSH,
0,
1,
{DW_EH_PE_sdata2},
},
{
"DW_OP_const4u",
OP_PUSH,
0,
1,
{DW_EH_PE_udata4},
},
{
"DW_OP_const4s",
OP_PUSH,
0,
1,
{DW_EH_PE_sdata4},
},
{
"DW_OP_const8u",
OP_PUSH,
0,
1,
{DW_EH_PE_udata8},
},
{
"DW_OP_const8s",
OP_PUSH,
0,
1,
{DW_EH_PE_sdata8},
},
{
"DW_OP_constu",
OP_PUSH,
0,
1,
{DW_EH_PE_uleb128},
},
{
"DW_OP_consts",
OP_PUSH,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_dup",
OP_DUP,
1,
0,
{},
},
{
"DW_OP_drop",
OP_DROP,
1,
0,
{},
},
{
"DW_OP_over",
OP_OVER,
2,
0,
{},
},
{
"DW_OP_pick",
OP_PICK,
0,
1,
{DW_EH_PE_udata1},
},
{
"DW_OP_swap",
OP_SWAP,
2,
0,
{},
},
{
"DW_OP_rot",
OP_ROT,
3,
0,
{},
},
{
"DW_OP_xderef",
OP_NOT_IMPLEMENTED,
2,
0,
{},
},
{
"DW_OP_abs",
OP_ABS,
1,
0,
{},
},
{
"DW_OP_and",
OP_AND,
2,
0,
{},
},
{
"DW_OP_div",
OP_DIV,
2,
0,
{},
},
{
"DW_OP_minus",
OP_MINUS,
2,
0,
{},
},
{
"DW_OP_mod",
OP_MOD,
2,
0,
{},
},
{
"DW_OP_mul",
OP_MUL,
2,
0,
{},
},
{
"DW_OP_neg",
OP_NEG,
1,
0,
{},
},
{
"DW_OP_not",
OP_NOT,
1,
0,
{},
},
{
"DW_OP_or",
OP_OR,
2,
0,
{},
},
{
"DW_OP_plus",
OP_PLUS,
2,
0,
{},
},
{
"DW_OP_plus_uconst",
OP_PLUS_UCONST,
1,
1,
{DW_EH_PE_uleb128},
},
{
"DW_OP_shl",
OP_SHL,
2,
0,
{},
},
{
"DW_OP_shr",
OP_SHR,
2,
0,
{},
},
{
"DW_OP_shra",
OP_SHRA,
2,
0,
{},
},
{
"DW_OP_xor",
OP_XOR,
2,
0,
{},
},
{
"DW_OP_bra",
OP_BRA,
1,
1,
{DW_EH_PE_sdata2},
},
{
"DW_OP_eq",
OP_EQ,
2,
0,
{},
},
{
"DW_OP_ge",
OP_GE,
2,
0,
{},
},
{
"DW_OP_gt",
OP_GT,
2,
0,
{},
},
{
"DW_OP_le",
OP_LE,
2,
0,
{},
},
{
"DW_OP_lt",
OP_LT,
2,
0,
{},
},
{
"DW_OP_ne",
OP_NE,
2,
0,
{},
},
{
"DW_OP_skip",
OP_SKIP,
0,
1,
{DW_EH_PE_sdata2},
},
{
"DW_OP_lit0",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit1",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit2",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit3",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit4",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit5",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit6",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit7",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit8",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit9",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit10",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit11",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit12",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit13",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit14",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit15",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit16",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit17",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit18",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit19",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit20",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit21",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit22",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit23",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit24",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit25",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit26",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit27",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit28",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit29",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit30",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_lit31",
OP_LIT,
0,
0,
{},
},
{
"DW_OP_reg0",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg1",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg2",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg3",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg4",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg5",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg6",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg7",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg8",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg9",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg10",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg11",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg12",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg13",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg14",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg15",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg16",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg17",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg18",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg19",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg20",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg21",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg22",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg23",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg24",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg25",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg26",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg27",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg28",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg29",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg30",
OP_REG,
0,
0,
{},
},
{
"DW_OP_reg31",
OP_REG,
0,
0,
{},
},
{
"DW_OP_breg0",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg1",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg2",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg3",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg4",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg5",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg6",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg7",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg8",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg9",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg10",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg11",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg12",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg13",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg14",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg15",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg16",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg17",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg18",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg19",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg20",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg21",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg22",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg23",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg24",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg25",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg26",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg27",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg28",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg29",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg30",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_breg31",
OP_BREG,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_regx",
OP_REGX,
0,
1,
{DW_EH_PE_uleb128},
},
{
"DW_OP_fbreg",
OP_NOT_IMPLEMENTED,
0,
1,
{DW_EH_PE_sleb128},
},
{
"DW_OP_bregx",
OP_BREGX,
0,
2,
{DW_EH_PE_uleb128, DW_EH_PE_sleb128},
},
{
"DW_OP_piece",
OP_NOT_IMPLEMENTED,
0,
1,
{DW_EH_PE_uleb128},
},
{
"DW_OP_deref_size",
OP_DEREF_SIZE,
1,
1,
{DW_EH_PE_udata1},
},
{
"DW_OP_xderef_size",
OP_NOT_IMPLEMENTED,
0,
1,
{DW_EH_PE_udata1},
},
{
"DW_OP_nop",
OP_NOP,
0,
0,
{},
},
{
"DW_OP_push_object_address",
OP_NOT_IMPLEMENTED,
0,
0,
{},
},
{
"DW_OP_call2",
OP_NOT_IMPLEMENTED,
0,
1,
{DW_EH_PE_udata2},
},
{
"DW_OP_call4",
OP_NOT_IMPLEMENTED,
0,
1,
{DW_EH_PE_udata4},
},
{
"DW_OP_call_ref",
OP_NOT_IMPLEMENTED,
0,
0, {},
},
{
"DW_OP_form_tls_address",
OP_NOT_IMPLEMENTED,
0,
0,
{},
},
{
"DW_OP_call_frame_cfa",
OP_NOT_IMPLEMENTED,
0,
0,
{},
},
{
"DW_OP_bit_piece",
OP_NOT_IMPLEMENTED,
0,
2,
{DW_EH_PE_uleb128, DW_EH_PE_uleb128},
},
{
"DW_OP_implicit_value",
OP_NOT_IMPLEMENTED,
0,
1,
{DW_EH_PE_uleb128},
},
{
"DW_OP_stack_value",
OP_NOT_IMPLEMENTED,
1,
0,
{},
},
{"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, {"", OP_ILLEGAL, 0, 0, {}}, };
template <typename AddressType>
const typename DwarfOp<AddressType>::OpHandleFuncPtr DwarfOp<AddressType>::kOpHandleFuncList[] = {
[OP_ILLEGAL] = nullptr,
[OP_DEREF] = &DwarfOp<AddressType>::op_deref,
[OP_DEREF_SIZE] = &DwarfOp<AddressType>::op_deref_size,
[OP_PUSH] = &DwarfOp<AddressType>::op_push,
[OP_DUP] = &DwarfOp<AddressType>::op_dup,
[OP_DROP] = &DwarfOp<AddressType>::op_drop,
[OP_OVER] = &DwarfOp<AddressType>::op_over,
[OP_PICK] = &DwarfOp<AddressType>::op_pick,
[OP_SWAP] = &DwarfOp<AddressType>::op_swap,
[OP_ROT] = &DwarfOp<AddressType>::op_rot,
[OP_ABS] = &DwarfOp<AddressType>::op_abs,
[OP_AND] = &DwarfOp<AddressType>::op_and,
[OP_DIV] = &DwarfOp<AddressType>::op_div,
[OP_MINUS] = &DwarfOp<AddressType>::op_minus,
[OP_MOD] = &DwarfOp<AddressType>::op_mod,
[OP_MUL] = &DwarfOp<AddressType>::op_mul,
[OP_NEG] = &DwarfOp<AddressType>::op_neg,
[OP_NOT] = &DwarfOp<AddressType>::op_not,
[OP_OR] = &DwarfOp<AddressType>::op_or,
[OP_PLUS] = &DwarfOp<AddressType>::op_plus,
[OP_PLUS_UCONST] = &DwarfOp<AddressType>::op_plus_uconst,
[OP_SHL] = &DwarfOp<AddressType>::op_shl,
[OP_SHR] = &DwarfOp<AddressType>::op_shr,
[OP_SHRA] = &DwarfOp<AddressType>::op_shra,
[OP_XOR] = &DwarfOp<AddressType>::op_xor,
[OP_BRA] = &DwarfOp<AddressType>::op_bra,
[OP_EQ] = &DwarfOp<AddressType>::op_eq,
[OP_GE] = &DwarfOp<AddressType>::op_ge,
[OP_GT] = &DwarfOp<AddressType>::op_gt,
[OP_LE] = &DwarfOp<AddressType>::op_le,
[OP_LT] = &DwarfOp<AddressType>::op_lt,
[OP_NE] = &DwarfOp<AddressType>::op_ne,
[OP_SKIP] = &DwarfOp<AddressType>::op_skip,
[OP_LIT] = &DwarfOp<AddressType>::op_lit,
[OP_REG] = &DwarfOp<AddressType>::op_reg,
[OP_REGX] = &DwarfOp<AddressType>::op_regx,
[OP_BREG] = &DwarfOp<AddressType>::op_breg,
[OP_BREGX] = &DwarfOp<AddressType>::op_bregx,
[OP_NOP] = &DwarfOp<AddressType>::op_nop,
[OP_NOT_IMPLEMENTED] = &DwarfOp<AddressType>::op_not_implemented,
};
template <typename AddressType>
bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end) {
is_register_ = false;
stack_.clear();
memory_->set_cur_offset(start);
dex_pc_set_ = false;
if (memory_->cur_offset() < end) {
if (!Decode()) {
return false;
}
} else {
return true;
}
bool check_for_drop;
if (cur_op_ == 0x0c && operands_.back() == 0x31584544) {
check_for_drop = true;
} else {
check_for_drop = false;
}
if (memory_->cur_offset() < end) {
if (!Decode()) {
return false;
}
} else {
return true;
}
if (check_for_drop && cur_op_ == 0x13) {
dex_pc_set_ = true;
}
uint32_t iterations = 2;
while (memory_->cur_offset() < end) {
if (!Decode()) {
return false;
}
if (iterations++ == 1000) {
last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS;
return false;
}
}
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::Decode() {
last_error_.code = DWARF_ERROR_NONE;
if (!memory_->ReadBytes(&cur_op_, 1)) {
last_error_.code = DWARF_ERROR_MEMORY_INVALID;
last_error_.address = memory_->cur_offset();
return false;
}
const auto* op = &kCallbackTable[cur_op_];
if (op->handle_func == OP_ILLEGAL) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
const auto handle_func = kOpHandleFuncList[op->handle_func];
if (stack_.size() < op->num_required_stack_values) {
last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
return false;
}
operands_.clear();
for (size_t i = 0; i < op->num_operands; i++) {
uint64_t value;
if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
last_error_.code = DWARF_ERROR_MEMORY_INVALID;
last_error_.address = memory_->cur_offset();
return false;
}
operands_.push_back(value);
}
return (this->*handle_func)();
}
template <typename AddressType>
void DwarfOp<AddressType>::GetLogInfo(uint64_t start, uint64_t end,
std::vector<std::string>* lines) {
memory_->set_cur_offset(start);
while (memory_->cur_offset() < end) {
uint8_t cur_op;
if (!memory_->ReadBytes(&cur_op, 1)) {
return;
}
std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op));
std::string log_string;
const auto* op = &kCallbackTable[cur_op];
if (op->handle_func == OP_ILLEGAL) {
log_string = "Illegal";
} else {
log_string = op->name;
uint64_t start_offset = memory_->cur_offset();
for (size_t i = 0; i < op->num_operands; i++) {
uint64_t value;
if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
return;
}
log_string += ' ' + std::to_string(value);
}
uint64_t end_offset = memory_->cur_offset();
memory_->set_cur_offset(start_offset);
for (size_t i = start_offset; i < end_offset; i++) {
uint8_t byte;
if (!memory_->ReadBytes(&byte, 1)) {
return;
}
raw_string += android::base::StringPrintf(" 0x%02x", byte);
}
memory_->set_cur_offset(end_offset);
}
lines->push_back(std::move(log_string));
lines->push_back(std::move(raw_string));
}
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_deref() {
AddressType addr = StackPop();
AddressType value;
if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) {
last_error_.code = DWARF_ERROR_MEMORY_INVALID;
last_error_.address = addr;
return false;
}
stack_.push_front(value);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_deref_size() {
AddressType bytes_to_read = OperandAt(0);
if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
AddressType addr = StackPop();
AddressType value = 0;
if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) {
last_error_.code = DWARF_ERROR_MEMORY_INVALID;
last_error_.address = addr;
return false;
}
stack_.push_front(value);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_push() {
for (auto operand : operands_) {
stack_.push_front(operand);
}
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_dup() {
stack_.push_front(StackAt(0));
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_drop() {
StackPop();
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_over() {
stack_.push_front(StackAt(1));
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_pick() {
AddressType index = OperandAt(0);
if (index >= StackSize()) {
last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
return false;
}
stack_.push_front(StackAt(index));
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_swap() {
AddressType old_value = stack_[0];
stack_[0] = stack_[1];
stack_[1] = old_value;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_rot() {
AddressType top = stack_[0];
stack_[0] = stack_[1];
stack_[1] = stack_[2];
stack_[2] = top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_abs() {
SignedType signed_value = static_cast<SignedType>(stack_[0]);
if (signed_value < 0) {
signed_value = -signed_value;
}
stack_[0] = static_cast<AddressType>(signed_value);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_and() {
AddressType top = StackPop();
stack_[0] &= top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_div() {
AddressType top = StackPop();
if (top == 0) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
SignedType signed_divisor = static_cast<SignedType>(top);
SignedType signed_dividend = static_cast<SignedType>(stack_[0]);
stack_[0] = static_cast<AddressType>(signed_dividend / signed_divisor);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_minus() {
AddressType top = StackPop();
stack_[0] -= top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_mod() {
AddressType top = StackPop();
if (top == 0) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
stack_[0] %= top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_mul() {
AddressType top = StackPop();
stack_[0] *= top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_neg() {
SignedType signed_value = static_cast<SignedType>(stack_[0]);
stack_[0] = static_cast<AddressType>(-signed_value);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_not() {
stack_[0] = ~stack_[0];
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_or() {
AddressType top = StackPop();
stack_[0] |= top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_plus() {
AddressType top = StackPop();
stack_[0] += top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_plus_uconst() {
stack_[0] += OperandAt(0);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_shl() {
AddressType top = StackPop();
stack_[0] <<= top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_shr() {
AddressType top = StackPop();
stack_[0] >>= top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_shra() {
AddressType top = StackPop();
SignedType signed_value = static_cast<SignedType>(stack_[0]) >> top;
stack_[0] = static_cast<AddressType>(signed_value);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_xor() {
AddressType top = StackPop();
stack_[0] ^= top;
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_bra() {
AddressType top = StackPop();
int16_t offset = static_cast<int16_t>(OperandAt(0));
uint64_t cur_offset;
if (top != 0) {
cur_offset = memory_->cur_offset() + offset;
} else {
cur_offset = memory_->cur_offset() - offset;
}
memory_->set_cur_offset(cur_offset);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_eq() {
AddressType top = StackPop();
stack_[0] = bool_to_dwarf_bool(stack_[0] == top);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_ge() {
AddressType top = StackPop();
stack_[0] = bool_to_dwarf_bool(stack_[0] >= top);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_gt() {
AddressType top = StackPop();
stack_[0] = bool_to_dwarf_bool(stack_[0] > top);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_le() {
AddressType top = StackPop();
stack_[0] = bool_to_dwarf_bool(stack_[0] <= top);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_lt() {
AddressType top = StackPop();
stack_[0] = bool_to_dwarf_bool(stack_[0] < top);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_ne() {
AddressType top = StackPop();
stack_[0] = bool_to_dwarf_bool(stack_[0] != top);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_skip() {
int16_t offset = static_cast<int16_t>(OperandAt(0));
uint64_t cur_offset = memory_->cur_offset() + offset;
memory_->set_cur_offset(cur_offset);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_lit() {
stack_.push_front(cur_op() - 0x30);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_reg() {
is_register_ = true;
stack_.push_front(cur_op() - 0x50);
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_regx() {
is_register_ = true;
stack_.push_front(OperandAt(0));
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_breg() {
uint16_t reg = cur_op() - 0x70;
if (reg >= regs_info_->Total()) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
stack_.push_front(regs_info_->Get(reg) + OperandAt(0));
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_bregx() {
AddressType reg = OperandAt(0);
if (reg >= regs_info_->Total()) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
stack_.push_front(regs_info_->Get(reg) + OperandAt(1));
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_nop() {
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_not_implemented() {
last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
return false;
}
template class DwarfOp<uint32_t>;
template class DwarfOp<uint64_t>;
}