1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef DWARF_DEFINE_H 16 #define DWARF_DEFINE_H 17 18 #include <cinttypes> 19 #include <string> 20 #include <vector> 21 22 namespace OHOS { 23 namespace HiviewDFX { 24 #define DW_EH_VERSION 1 25 #define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ 26 #define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ 27 28 // https://dwarfstd.org/doc/DWARF5.pdf 29 // 7.7.1 DWARF Expressions 30 // Each operation is a 1-byte code that identifies that operation, followed by zero or more bytes of additional data 31 // Table 7.9: DWARF operation encodings 32 typedef enum { 33 DW_OP_reserved1 = 0x01, 34 DW_OP_reserved2, 35 DW_OP_addr, // constant address (size is target specific) 36 DW_OP_reserved4, 37 DW_OP_reserved5, 38 DW_OP_deref, 39 DW_OP_reserved7, 40 DW_OP_const1u, // 1-byte unsigned integer constant 41 DW_OP_const1s, // 1-byte signed integer constant 42 DW_OP_const2u, // 2-byte unsigned integer constant 43 DW_OP_const2s, // 2-byte signed integer constant 44 DW_OP_const4u, // 4-byte unsigned integer constant 45 DW_OP_const4s, // 4-byte signed integer constant 46 DW_OP_const8u, // 8-byte unsigned integer constant 47 DW_OP_const8s, // 8-byte signed integer constant 48 DW_OP_constu, // unsigned LEB128 integer constant 49 DW_OP_consts, // signed LEB128 integer constant 50 DW_OP_dup, 51 DW_OP_drop, 52 DW_OP_over, 53 DW_OP_pick, // 1-byte stack index 54 DW_OP_swap, 55 DW_OP_rot, 56 DW_OP_xderef, 57 DW_OP_abs, 58 DW_OP_and, 59 DW_OP_div, 60 DW_OP_minus, 61 DW_OP_mod, 62 DW_OP_mul, 63 DW_OP_neg, 64 DW_OP_not, 65 DW_OP_or, 66 DW_OP_plus, 67 DW_OP_plus_uconst, // ULEB128 addend 68 DW_OP_shl, 69 DW_OP_shr, 70 DW_OP_shra, 71 DW_OP_xor, 72 DW_OP_bra, // signed 2-byte constant 73 DW_OP_eq, 74 DW_OP_ge, 75 DW_OP_gt, 76 DW_OP_le, 77 DW_OP_lt, 78 DW_OP_ne, 79 DW_OP_skip, 80 DW_OP_lit0 = 0x30, // literals 0 .. 31 = (DW_OP_lit0 + literal) 81 DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, 82 DW_OP_lit5, DW_OP_lit6, DW_OP_lit7, DW_OP_lit8, 83 DW_OP_lit9, DW_OP_lit10, DW_OP_lit11, DW_OP_lit12, 84 DW_OP_lit13, DW_OP_lit14, DW_OP_lit15, DW_OP_lit16, 85 DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20, 86 DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, 87 DW_OP_lit25, DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, 88 DW_OP_lit29, DW_OP_lit30, DW_OP_lit31, 89 DW_OP_reg0 = 0x50, // reg 0 .. 31 = (DW_OP_reg0 + regnum) 90 DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, 91 DW_OP_reg5, DW_OP_reg6, DW_OP_reg7, DW_OP_reg8, 92 DW_OP_reg9, DW_OP_reg10, DW_OP_reg11, DW_OP_reg12, 93 DW_OP_reg13, DW_OP_reg14, DW_OP_reg15, DW_OP_reg16, 94 DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20, 95 DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, 96 DW_OP_reg25, DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, 97 DW_OP_reg29, DW_OP_reg30, DW_OP_reg31, 98 DW_OP_breg0 = 0x70, // SLEB128 offset base register 0 .. 31 = (DW_OP_breg0 + regnum) 99 DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, 100 DW_OP_breg5, DW_OP_breg6, DW_OP_breg7, DW_OP_breg8, 101 DW_OP_breg9, DW_OP_breg10, DW_OP_breg11, DW_OP_breg12, 102 DW_OP_breg13, DW_OP_breg14, DW_OP_breg15, DW_OP_breg16, 103 DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20, 104 DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, 105 DW_OP_breg25, DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, 106 DW_OP_breg29, DW_OP_breg30, DW_OP_breg31, 107 DW_OP_regx = 0x90, // ULEB128 register 108 DW_OP_fbreg, // SLEB128 offset 109 DW_OP_bregx, // ULEB128 register, SLEB128 offset 110 DW_OP_piece, // ULEB128 size of piece 111 DW_OP_deref_size, // 1-byte size of data retrieved 112 DW_OP_xderef_size, // 1-byte size of data retrieved 113 DW_OP_nop, 114 DW_OP_push_object_address, 115 DW_OP_call2, // 2-byte offset of DIE 116 DW_OP_call4, // 4-byte offset of DIE 117 DW_OP_call_ref, // 4- or 8-byte offset of DIE 118 // dwarf4 added 119 DW_OP_form_tls_address, 120 DW_OP_call_frame_cfa, 121 DW_OP_bit_piece, // ULEB128 size, ULEB128 offset 122 DW_OP_implicit_value, // ULEB128 size, block of that size 123 DW_OP_stack_value, 124 // dwarf5 added 125 DW_OP_implicit_pointer, // 4- or 8-byte offset of DIE, SLEB128 constant offset 126 DW_OP_addrx, // ULEB128 indirect address 127 DW_OP_constx, // ULEB128 indirect constant 128 DW_OP_entry_value, // ULEB128 size, block of that size 129 DW_OP_const_type, // ULEB128 type entry offset, 1-byte size, constant value 130 DW_OP_regval_type, // ULEB128 register number, ULEB128 constant offset 131 DW_OP_deref_type, // 1-byte size, ULEB128 type entry offset 132 DW_OP_xderef_type, // 1-byte size, ULEB128 type entry offset 133 DW_OP_convert_type, // ULEB128 type entry offset 134 DW_OP_reinterpret_type, // ULEB128 type entry offset 135 DW_OP_lo_user = 0xe0, 136 DW_OP_hi_user = 0xff 137 } DwarfOperater; 138 139 // DWARF Call Frame Information 140 // Call frame instructions are encoded in one or more bytes. The primary opcode is 141 // encoded in the high order two bits of the first byte (that is, opcode = byte >> 6). 142 // An operand or extended opcode may be encoded in the low order 6 bits. 143 // Table 7.29: Call frame instruction encodings 144 typedef enum { 145 DW_CFA_advance_loc = 0x40, // high 2-bits 0x1, low 6-bits delta 146 DW_CFA_offset = 0x80, // high 2-bits 0x2, low 6-bits register, ULEB128 offset 147 DW_CFA_restore = 0xc0, // high 2-bits 0x3, low 6-bits register 148 // the value is the lower 6-bits, Operand1, Operand2 149 DW_CFA_nop = 0x00, 150 DW_CFA_set_loc, // address 151 DW_CFA_advance_loc1, // 1-byte delta 152 DW_CFA_advance_loc2, // 2-byte delta 153 DW_CFA_advance_loc4, // 4-byte delta 154 DW_CFA_offset_extended, // ULEB128 register, ULEB128 offset 155 DW_CFA_restore_extended, // ULEB128 register 156 DW_CFA_undefined, // ULEB128 register 157 DW_CFA_same_value, // ULEB128 register 158 DW_CFA_register, // ULEB128 register, ULEB128 offset 159 DW_CFA_remember_state, 160 DW_CFA_restore_state, 161 DW_CFA_def_cfa, // ULEB128 register, ULEB128 offset 162 DW_CFA_def_cfa_register, // ULEB128 register 163 DW_CFA_def_cfa_offset, // ULEB128 offset 164 DW_CFA_def_cfa_expression, // BLOCK 165 DW_CFA_expression = 0x10, // ULEB128 register, BLOCK 166 DW_CFA_offset_extended_sf, // ULEB128 register, SLEB128 offset 167 DW_CFA_def_cfa_sf, // ULEB128 register, SLEB128 offset 168 DW_CFA_def_cfa_offset_sf, // SLEB128 offset 169 DW_CFA_val_offset, // ULEB128, ULEB128 170 DW_CFA_val_offset_sf, // ULEB128, SLEB128 171 DW_CFA_val_expression, // ULEB128, BLOCK 172 173 DW_CFA_lo_user = 0x1c, 174 DW_CFA_AARCH64_negate_ra_state = 0x2d, 175 // GNU extensions 176 DW_CFA_GNU_args_size = 0x2e, 177 DW_CFA_GNU_negative_offset_extended = 0x2f, 178 179 DW_CFA_hi_user = 0x3c, 180 } DwarfCfa; 181 182 enum DwarfEncoding : uint8_t { 183 DW_EH_PE_omit = 0xff, 184 185 DW_EH_PE_absptr = 0x00, 186 DW_EH_PE_uleb128 = 0x01, 187 DW_EH_PE_udata2 = 0x02, 188 DW_EH_PE_udata4 = 0x03, 189 DW_EH_PE_udata8 = 0x04, 190 DW_EH_PE_sleb128 = 0x09, 191 DW_EH_PE_sdata2 = 0x0a, 192 DW_EH_PE_sdata4 = 0x0b, 193 DW_EH_PE_sdata8 = 0x0c, 194 195 DW_EH_PE_pcrel = 0x10, 196 DW_EH_PE_textrel = 0x20, 197 DW_EH_PE_datarel = 0x30, 198 DW_EH_PE_funcrel = 0x40, 199 DW_EH_PE_aligned = 0x50, 200 DW_EH_PE_indirect = 0x80, 201 202 DW_EH_PE_udata1 = 0x0d, 203 DW_EH_PE_sdata1 = 0x0e, 204 DW_EH_PE_block = 0x0f, 205 }; 206 207 // we only need to parse eh_frame and eh_frame_hdr to get the dwarf-encoded unwind info 208 // https://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 209 // Parsed Common Information Entry Format 210 struct CommonInfoEntry { 211 uint32_t codeAlignFactor = 0; 212 int32_t dataAlignFactor = 0; 213 uintptr_t returnAddressRegister = 0; 214 bool hasAugmentationData = false; 215 bool isSignalFrame = false; 216 uint8_t segmentSize = 0; 217 uintptr_t instructionsOff = 0; 218 uintptr_t instructionsEnd = 0; 219 // P 220 uint8_t personality = 0; 221 // L 222 uint8_t lsdaEncoding = 0; 223 // R 224 uint8_t pointerEncoding = 0; 225 }; 226 227 // Parsed Frame Description Entry 228 // Table 8-3. Frame Description Entry Format 229 struct FrameDescEntry { 230 uintptr_t pcStart = 0; 231 uintptr_t pcEnd = 0; 232 uintptr_t lsda = 0; 233 uintptr_t instructionsOff = 0; 234 uintptr_t instructionsEnd = 0; 235 uintptr_t cieAddr = 0; 236 CommonInfoEntry cie; 237 }; 238 239 struct DwarfTableEntry { 240 int32_t startPc = 0; 241 int32_t fdeOffset = 0; 242 }; 243 244 } // namespace HiviewDFX 245 } // namespace OHOS 246 #endif 247