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