Source/PLCrashAsyncDwarfExpression.hpp (181 lines of code) (raw):

/* * Copyright (c) 2013 Plausible Labs Cooperative, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef PLCRASH_ASYNC_DWARF_EXPRESSION_H #define PLCRASH_ASYNC_DWARF_EXPRESSION_H 1 #include "PLCrashAsync.h" #include "PLCrashAsyncMObject.h" #include "PLCrashAsyncThread.h" #include "PLCrashFeatureConfig.h" #include "PLCrashMacros.h" #if PLCRASH_FEATURE_UNWIND_DWARF PLCR_CPP_BEGIN_NS namespace async { /** * @internal * @ingroup plcrash_async_dwarf * @{ */ /** * DWARF expression opcodes, as defined by the DWARF 3 Specification (Section 7.7.1). * * @internal * * The table was automatically generated from the DWARF specification using the * following awk script. * * @code * /^DW_/ { * opcode = $0 * } * * !/^DW_/ { * printf " /\** %s", opcode * * if ($2 > 1) { * printf(", accepts %d operands.", $2); * } else if ($2 == 1) { * printf(", accepts %d operand.", $2); * } else { * printf(", accepts no operands.") * } * * if (NF > 2) { * for (i = 3; i <= NF; i++) { * printf " %s", $i * } * } * printf " *\/\n" * printf " %s = %s,\n\n", opcode, $1 * * # Special case 'range' opcodes that are not included in the spec table * if (opcode == "DW_OP_lit1") { * for (i = 2; i < 31; i++) { * printf(" /\* Literal %d value; see DW_OP_lit0. *\/\n", i) * printf(" DW_OP_lit%d = 0x%x,\n\n", i, val+i-1) * } * } else if (opcode == "DW_OP_reg1") { * for (i = 2; i < 31; i++) { * printf(" /\* Register number; see DW_OP_reg0. *\/\n") * printf(" DW_OP_reg%d = 0x%x,\n\n", i, val+i-1) * } * } else if (opcode == "DW_OP_breg1") { * for (i = 2; i < 31; i++) { * printf(" /\* Register number; see DW_OP_breg0. *\/\n") * printf(" DW_OP_breg%d = 0x%x,\n\n", i, val+i-1) * } * } * } * @endcode */ typedef enum DW_OP { /** DW_OP_addr, accepts 1 operand. constant address (size target specific) */ DW_OP_addr = 0x03, /** DW_OP_deref, accepts no operands. */ DW_OP_deref = 0x06, /** DW_OP_const1u, accepts 1 operand. 1-byte constant */ DW_OP_const1u = 0x08, /** DW_OP_const1s, accepts 1 operand. 1-byte constant */ DW_OP_const1s = 0x09, /** DW_OP_const2u, accepts 1 operand. 2-byte constant */ DW_OP_const2u = 0x0a, /** DW_OP_const2s, accepts 1 operand. 2-byte constant */ DW_OP_const2s = 0x0b, /** DW_OP_const4u, accepts 1 operand. 4-byte constant */ DW_OP_const4u = 0x0c, /** DW_OP_const4s, accepts 1 operand. 4-byte constant */ DW_OP_const4s = 0x0d, /** DW_OP_const8u, accepts 1 operand. 8-byte constant */ DW_OP_const8u = 0x0e, /** DW_OP_const8s, accepts 1 operand. 8-byte constant */ DW_OP_const8s = 0x0f, /** DW_OP_constu, accepts 1 operand. ULEB128 constant */ DW_OP_constu = 0x10, /** DW_OP_consts, accepts 1 operand. SLEB128 constant */ DW_OP_consts = 0x11, /** DW_OP_dup, accepts no operands. */ DW_OP_dup = 0x12, /** DW_OP_drop, accepts no operands. */ DW_OP_drop = 0x13, /** DW_OP_over, accepts no operands. */ DW_OP_over = 0x14, /** DW_OP_pick, accepts 1 operand. 1-byte stack index */ DW_OP_pick = 0x15, /** DW_OP_swap, accepts no operands. */ DW_OP_swap = 0x16, /** DW_OP_rot, accepts no operands. */ DW_OP_rot = 0x17, /** DW_OP_xderef, accepts no operands. */ DW_OP_xderef = 0x18, /** DW_OP_abs, accepts no operands. */ DW_OP_abs = 0x19, /** DW_OP_and, accepts no operands. */ DW_OP_and = 0x1a, /** DW_OP_div, accepts no operands. */ DW_OP_div = 0x1b, /** DW_OP_minus, accepts no operands. */ DW_OP_minus = 0x1c, /** DW_OP_mod, accepts no operands. */ DW_OP_mod = 0x1d, /** DW_OP_mul, accepts no operands. */ DW_OP_mul = 0x1e, /** DW_OP_neg, accepts no operands. */ DW_OP_neg = 0x1f, /** DW_OP_not, accepts no operands. */ DW_OP_not = 0x20, /** DW_OP_or, accepts no operands. */ DW_OP_or = 0x21, /** DW_OP_plus, accepts no operands. */ DW_OP_plus = 0x22, /** DW_OP_plus_uconst, accepts 1 operand. ULEB128 addend */ DW_OP_plus_uconst = 0x23, /** DW_OP_shl, accepts no operands. */ DW_OP_shl = 0x24, /** DW_OP_shr, accepts no operands. */ DW_OP_shr = 0x25, /** DW_OP_shra, accepts no operands. */ DW_OP_shra = 0x26, /** DW_OP_xor, accepts no operands. */ DW_OP_xor = 0x27, /** DW_OP_skip, accepts 1 operand. signed 2-byte constant */ DW_OP_skip = 0x2f, /** DW_OP_bra, accepts 1 operand. signed 2-byte constant */ DW_OP_bra = 0x28, /** DW_OP_eq, accepts no operands. */ DW_OP_eq = 0x29, /** DW_OP_ge, accepts no operands. */ DW_OP_ge = 0x2a, /** DW_OP_gt, accepts no operands. */ DW_OP_gt = 0x2b, /** DW_OP_le, accepts no operands. */ DW_OP_le = 0x2c, /** DW_OP_lt, accepts no operands. */ DW_OP_lt = 0x2d, /** DW_OP_ne, accepts no operands. */ DW_OP_ne = 0x2e, /** DW_OP_lit0, accepts no operands. literals 0..31 = (DW_OP_lit0 + literal) */ DW_OP_lit0 = 0x30, /** DW_OP_lit1, accepts no operands. ... */ DW_OP_lit1 = 0x31, /* Literal 2 value; see DW_OP_lit0. */ DW_OP_lit2 = 0x32, /* Literal 3 value; see DW_OP_lit0. */ DW_OP_lit3 = 0x33, /* Literal 4 value; see DW_OP_lit0. */ DW_OP_lit4 = 0x34, /* Literal 5 value; see DW_OP_lit0. */ DW_OP_lit5 = 0x35, /* Literal 6 value; see DW_OP_lit0. */ DW_OP_lit6 = 0x36, /* Literal 7 value; see DW_OP_lit0. */ DW_OP_lit7 = 0x37, /* Literal 8 value; see DW_OP_lit0. */ DW_OP_lit8 = 0x38, /* Literal 9 value; see DW_OP_lit0. */ DW_OP_lit9 = 0x39, /* Literal 10 value; see DW_OP_lit0. */ DW_OP_lit10 = 0x3a, /* Literal 11 value; see DW_OP_lit0. */ DW_OP_lit11 = 0x3b, /* Literal 12 value; see DW_OP_lit0. */ DW_OP_lit12 = 0x3c, /* Literal 13 value; see DW_OP_lit0. */ DW_OP_lit13 = 0x3d, /* Literal 14 value; see DW_OP_lit0. */ DW_OP_lit14 = 0x3e, /* Literal 15 value; see DW_OP_lit0. */ DW_OP_lit15 = 0x3f, /* Literal 16 value; see DW_OP_lit0. */ DW_OP_lit16 = 0x40, /* Literal 17 value; see DW_OP_lit0. */ DW_OP_lit17 = 0x41, /* Literal 18 value; see DW_OP_lit0. */ DW_OP_lit18 = 0x42, /* Literal 19 value; see DW_OP_lit0. */ DW_OP_lit19 = 0x43, /* Literal 20 value; see DW_OP_lit0. */ DW_OP_lit20 = 0x44, /* Literal 21 value; see DW_OP_lit0. */ DW_OP_lit21 = 0x45, /* Literal 22 value; see DW_OP_lit0. */ DW_OP_lit22 = 0x46, /* Literal 23 value; see DW_OP_lit0. */ DW_OP_lit23 = 0x47, /* Literal 24 value; see DW_OP_lit0. */ DW_OP_lit24 = 0x48, /* Literal 25 value; see DW_OP_lit0. */ DW_OP_lit25 = 0x49, /* Literal 26 value; see DW_OP_lit0. */ DW_OP_lit26 = 0x4a, /* Literal 27 value; see DW_OP_lit0. */ DW_OP_lit27 = 0x4b, /* Literal 28 value; see DW_OP_lit0. */ DW_OP_lit28 = 0x4c, /* Literal 29 value; see DW_OP_lit0. */ DW_OP_lit29 = 0x4d, /* Literal 30 value; see DW_OP_lit0. */ DW_OP_lit30 = 0x4e, /** DW_OP_lit31, accepts no operands. */ DW_OP_lit31 = 0x4f, /** DW_OP_reg0, accepts no operands. reg 0..31 = (DW_OP_reg0 + regnum) */ DW_OP_reg0 = 0x50, /** DW_OP_reg1, accepts no operands. ... */ DW_OP_reg1 = 0x51, /* Register number; see DW_OP_reg0. */ DW_OP_reg2 = 0x52, /* Register number; see DW_OP_reg0. */ DW_OP_reg3 = 0x53, /* Register number; see DW_OP_reg0. */ DW_OP_reg4 = 0x54, /* Register number; see DW_OP_reg0. */ DW_OP_reg5 = 0x55, /* Register number; see DW_OP_reg0. */ DW_OP_reg6 = 0x56, /* Register number; see DW_OP_reg0. */ DW_OP_reg7 = 0x57, /* Register number; see DW_OP_reg0. */ DW_OP_reg8 = 0x58, /* Register number; see DW_OP_reg0. */ DW_OP_reg9 = 0x59, /* Register number; see DW_OP_reg0. */ DW_OP_reg10 = 0x5a, /* Register number; see DW_OP_reg0. */ DW_OP_reg11 = 0x5b, /* Register number; see DW_OP_reg0. */ DW_OP_reg12 = 0x5c, /* Register number; see DW_OP_reg0. */ DW_OP_reg13 = 0x5d, /* Register number; see DW_OP_reg0. */ DW_OP_reg14 = 0x5e, /* Register number; see DW_OP_reg0. */ DW_OP_reg15 = 0x5f, /* Register number; see DW_OP_reg0. */ DW_OP_reg16 = 0x60, /* Register number; see DW_OP_reg0. */ DW_OP_reg17 = 0x61, /* Register number; see DW_OP_reg0. */ DW_OP_reg18 = 0x62, /* Register number; see DW_OP_reg0. */ DW_OP_reg19 = 0x63, /* Register number; see DW_OP_reg0. */ DW_OP_reg20 = 0x64, /* Register number; see DW_OP_reg0. */ DW_OP_reg21 = 0x65, /* Register number; see DW_OP_reg0. */ DW_OP_reg22 = 0x66, /* Register number; see DW_OP_reg0. */ DW_OP_reg23 = 0x67, /* Register number; see DW_OP_reg0. */ DW_OP_reg24 = 0x68, /* Register number; see DW_OP_reg0. */ DW_OP_reg25 = 0x69, /* Register number; see DW_OP_reg0. */ DW_OP_reg26 = 0x6a, /* Register number; see DW_OP_reg0. */ DW_OP_reg27 = 0x6b, /* Register number; see DW_OP_reg0. */ DW_OP_reg28 = 0x6c, /* Register number; see DW_OP_reg0. */ DW_OP_reg29 = 0x6d, /* Register number; see DW_OP_reg0. */ DW_OP_reg30 = 0x6e, /** DW_OP_reg31, accepts no operands. */ DW_OP_reg31 = 0x6f, /** DW_OP_breg0, accepts 1 operand. SLEB128 offset base register 0..31 = (DW_OP_breg0 + regnum) */ DW_OP_breg0 = 0x70, /** DW_OP_breg1, accepts 1 operand. ... */ DW_OP_breg1 = 0x71, /* Register number; see DW_OP_breg0. */ DW_OP_breg2 = 0x72, /* Register number; see DW_OP_breg0. */ DW_OP_breg3 = 0x73, /* Register number; see DW_OP_breg0. */ DW_OP_breg4 = 0x74, /* Register number; see DW_OP_breg0. */ DW_OP_breg5 = 0x75, /* Register number; see DW_OP_breg0. */ DW_OP_breg6 = 0x76, /* Register number; see DW_OP_breg0. */ DW_OP_breg7 = 0x77, /* Register number; see DW_OP_breg0. */ DW_OP_breg8 = 0x78, /* Register number; see DW_OP_breg0. */ DW_OP_breg9 = 0x79, /* Register number; see DW_OP_breg0. */ DW_OP_breg10 = 0x7a, /* Register number; see DW_OP_breg0. */ DW_OP_breg11 = 0x7b, /* Register number; see DW_OP_breg0. */ DW_OP_breg12 = 0x7c, /* Register number; see DW_OP_breg0. */ DW_OP_breg13 = 0x7d, /* Register number; see DW_OP_breg0. */ DW_OP_breg14 = 0x7e, /* Register number; see DW_OP_breg0. */ DW_OP_breg15 = 0x7f, /* Register number; see DW_OP_breg0. */ DW_OP_breg16 = 0x80, /* Register number; see DW_OP_breg0. */ DW_OP_breg17 = 0x81, /* Register number; see DW_OP_breg0. */ DW_OP_breg18 = 0x82, /* Register number; see DW_OP_breg0. */ DW_OP_breg19 = 0x83, /* Register number; see DW_OP_breg0. */ DW_OP_breg20 = 0x84, /* Register number; see DW_OP_breg0. */ DW_OP_breg21 = 0x85, /* Register number; see DW_OP_breg0. */ DW_OP_breg22 = 0x86, /* Register number; see DW_OP_breg0. */ DW_OP_breg23 = 0x87, /* Register number; see DW_OP_breg0. */ DW_OP_breg24 = 0x88, /* Register number; see DW_OP_breg0. */ DW_OP_breg25 = 0x89, /* Register number; see DW_OP_breg0. */ DW_OP_breg26 = 0x8a, /* Register number; see DW_OP_breg0. */ DW_OP_breg27 = 0x8b, /* Register number; see DW_OP_breg0. */ DW_OP_breg28 = 0x8c, /* Register number; see DW_OP_breg0. */ DW_OP_breg29 = 0x8d, /* Register number; see DW_OP_breg0. */ DW_OP_breg30 = 0x8e, /** DW_OP_breg31, accepts 1 operand. */ DW_OP_breg31 = 0x8f, /** DW_OP_regx, accepts 1 operand. ULEB128 register */ DW_OP_regx = 0x90, /** DW_OP_fbreg, accepts 1 operand. SLEB128 offset */ DW_OP_fbreg = 0x91, /** DW_OP_bregx, accepts 2 operands. ULEB128 register followed by SLEB128 offset */ DW_OP_bregx = 0x92, /** DW_OP_piece, accepts 1 operand. ULEB128 size of piece addressed */ DW_OP_piece = 0x93, /** DW_OP_deref_size, accepts 1 operand. 1-byte size of data retrieved */ DW_OP_deref_size = 0x94, /** DW_OP_xderef_size, accepts 1 operand. 1-byte size of data retrieved */ DW_OP_xderef_size = 0x95, /** DW_OP_nop, accepts no operands. */ DW_OP_nop = 0x96, /** DW_OP_push_object_address, accepts no operands. */ DW_OP_push_object_address = 0x97, /** DW_OP_call2, accepts 1 operand. 2-byte offset of DIE */ DW_OP_call2 = 0x98, /** DW_OP_call4, accepts 1 operand. 4-byte offset of DIE */ DW_OP_call4 = 0x99, /** DW_OP_call_ref, accepts 1 operand. 4- or 8-byte offset of DIE */ DW_OP_call_ref = 0x9a, /** DW_OP_form_tls_address, accepts no operands. */ DW_OP_form_tls_address = 0x9b, /** DW_OP_call_frame_cfa, accepts no operands. */ DW_OP_call_frame_cfa = 0x9c, /** DW_OP_bit_piece, accepts 2 operands. */ DW_OP_bit_piece = 0x9d, /** DW_OP_lo_user, accepts no operands. */ DW_OP_lo_user = 0xe0, /** DW_OP_hi_user, accepts no operands. */ DW_OP_hi_user = 0xff, } DW_OP_t; template <typename machine_ptr, typename machine_ptr_s> plcrash_error_t plcrash_async_dwarf_expression_eval (plcrash_async_mobject_t *mobj, task_t task, const plcrash_async_thread_state_t *thread_state, const plcrash_async_byteorder_t *byteorder, pl_vm_address_t address, pl_vm_off_t offset, pl_vm_size_t length, machine_ptr initial_state[], size_t initial_count, machine_ptr *result); /* * @} */ } PLCR_CPP_END_NS #endif /* PLCRASH_FEATURE_UNWIND_DWARF */ #endif /* PLCRASH_ASYNC_DWARF_CFA_H */