1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci#ifndef DWARF_DEFINE_H
16800b99b8Sopenharmony_ci#define DWARF_DEFINE_H
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <cinttypes>
19800b99b8Sopenharmony_ci#include <string>
20800b99b8Sopenharmony_ci#include <vector>
21800b99b8Sopenharmony_ci
22800b99b8Sopenharmony_cinamespace OHOS {
23800b99b8Sopenharmony_cinamespace HiviewDFX {
24800b99b8Sopenharmony_ci#define DW_EH_VERSION           1
25800b99b8Sopenharmony_ci#define DW_EH_PE_FORMAT_MASK    0x0f    /* format of the encoded value */
26800b99b8Sopenharmony_ci#define DW_EH_PE_APPL_MASK      0x70    /* how the value is to be applied */
27800b99b8Sopenharmony_ci
28800b99b8Sopenharmony_ci// https://dwarfstd.org/doc/DWARF5.pdf
29800b99b8Sopenharmony_ci// 7.7.1 DWARF Expressions
30800b99b8Sopenharmony_ci// Each operation is a 1-byte code that identifies that operation, followed by zero or more bytes of additional data
31800b99b8Sopenharmony_ci// Table 7.9: DWARF operation encodings
32800b99b8Sopenharmony_citypedef enum {
33800b99b8Sopenharmony_ci    DW_OP_reserved1 = 0x01,
34800b99b8Sopenharmony_ci    DW_OP_reserved2,
35800b99b8Sopenharmony_ci    DW_OP_addr,  // constant address (size is target specific)
36800b99b8Sopenharmony_ci    DW_OP_reserved4,
37800b99b8Sopenharmony_ci    DW_OP_reserved5,
38800b99b8Sopenharmony_ci    DW_OP_deref,
39800b99b8Sopenharmony_ci    DW_OP_reserved7,
40800b99b8Sopenharmony_ci    DW_OP_const1u,  // 1-byte unsigned integer constant
41800b99b8Sopenharmony_ci    DW_OP_const1s,  // 1-byte signed integer constant
42800b99b8Sopenharmony_ci    DW_OP_const2u,  // 2-byte unsigned integer constant
43800b99b8Sopenharmony_ci    DW_OP_const2s,  // 2-byte signed integer constant
44800b99b8Sopenharmony_ci    DW_OP_const4u,  // 4-byte unsigned integer constant
45800b99b8Sopenharmony_ci    DW_OP_const4s,  // 4-byte signed integer constant
46800b99b8Sopenharmony_ci    DW_OP_const8u,  // 8-byte unsigned integer constant
47800b99b8Sopenharmony_ci    DW_OP_const8s,  // 8-byte signed integer constant
48800b99b8Sopenharmony_ci    DW_OP_constu,   // unsigned LEB128 integer constant
49800b99b8Sopenharmony_ci    DW_OP_consts,   // signed LEB128 integer constant
50800b99b8Sopenharmony_ci    DW_OP_dup,
51800b99b8Sopenharmony_ci    DW_OP_drop,
52800b99b8Sopenharmony_ci    DW_OP_over,
53800b99b8Sopenharmony_ci    DW_OP_pick,  // 1-byte stack index
54800b99b8Sopenharmony_ci    DW_OP_swap,
55800b99b8Sopenharmony_ci    DW_OP_rot,
56800b99b8Sopenharmony_ci    DW_OP_xderef,
57800b99b8Sopenharmony_ci    DW_OP_abs,
58800b99b8Sopenharmony_ci    DW_OP_and,
59800b99b8Sopenharmony_ci    DW_OP_div,
60800b99b8Sopenharmony_ci    DW_OP_minus,
61800b99b8Sopenharmony_ci    DW_OP_mod,
62800b99b8Sopenharmony_ci    DW_OP_mul,
63800b99b8Sopenharmony_ci    DW_OP_neg,
64800b99b8Sopenharmony_ci    DW_OP_not,
65800b99b8Sopenharmony_ci    DW_OP_or,
66800b99b8Sopenharmony_ci    DW_OP_plus,
67800b99b8Sopenharmony_ci    DW_OP_plus_uconst,  // ULEB128 addend
68800b99b8Sopenharmony_ci    DW_OP_shl,
69800b99b8Sopenharmony_ci    DW_OP_shr,
70800b99b8Sopenharmony_ci    DW_OP_shra,
71800b99b8Sopenharmony_ci    DW_OP_xor,
72800b99b8Sopenharmony_ci    DW_OP_bra,  // signed 2-byte constant
73800b99b8Sopenharmony_ci    DW_OP_eq,
74800b99b8Sopenharmony_ci    DW_OP_ge,
75800b99b8Sopenharmony_ci    DW_OP_gt,
76800b99b8Sopenharmony_ci    DW_OP_le,
77800b99b8Sopenharmony_ci    DW_OP_lt,
78800b99b8Sopenharmony_ci    DW_OP_ne,
79800b99b8Sopenharmony_ci    DW_OP_skip,
80800b99b8Sopenharmony_ci    DW_OP_lit0 = 0x30,  // literals 0 .. 31 = (DW_OP_lit0 + literal)
81800b99b8Sopenharmony_ci    DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4,
82800b99b8Sopenharmony_ci    DW_OP_lit5, DW_OP_lit6, DW_OP_lit7, DW_OP_lit8,
83800b99b8Sopenharmony_ci    DW_OP_lit9, DW_OP_lit10, DW_OP_lit11, DW_OP_lit12,
84800b99b8Sopenharmony_ci    DW_OP_lit13, DW_OP_lit14, DW_OP_lit15, DW_OP_lit16,
85800b99b8Sopenharmony_ci    DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20,
86800b99b8Sopenharmony_ci    DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24,
87800b99b8Sopenharmony_ci    DW_OP_lit25, DW_OP_lit26, DW_OP_lit27, DW_OP_lit28,
88800b99b8Sopenharmony_ci    DW_OP_lit29, DW_OP_lit30, DW_OP_lit31,
89800b99b8Sopenharmony_ci    DW_OP_reg0 = 0x50,  // reg 0 .. 31 = (DW_OP_reg0 + regnum)
90800b99b8Sopenharmony_ci    DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4,
91800b99b8Sopenharmony_ci    DW_OP_reg5, DW_OP_reg6, DW_OP_reg7, DW_OP_reg8,
92800b99b8Sopenharmony_ci    DW_OP_reg9, DW_OP_reg10, DW_OP_reg11, DW_OP_reg12,
93800b99b8Sopenharmony_ci    DW_OP_reg13, DW_OP_reg14, DW_OP_reg15, DW_OP_reg16,
94800b99b8Sopenharmony_ci    DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20,
95800b99b8Sopenharmony_ci    DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24,
96800b99b8Sopenharmony_ci    DW_OP_reg25, DW_OP_reg26, DW_OP_reg27, DW_OP_reg28,
97800b99b8Sopenharmony_ci    DW_OP_reg29, DW_OP_reg30, DW_OP_reg31,
98800b99b8Sopenharmony_ci    DW_OP_breg0 = 0x70,  // SLEB128 offset base register 0 .. 31 = (DW_OP_breg0 + regnum)
99800b99b8Sopenharmony_ci    DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4,
100800b99b8Sopenharmony_ci    DW_OP_breg5, DW_OP_breg6, DW_OP_breg7, DW_OP_breg8,
101800b99b8Sopenharmony_ci    DW_OP_breg9, DW_OP_breg10, DW_OP_breg11, DW_OP_breg12,
102800b99b8Sopenharmony_ci    DW_OP_breg13, DW_OP_breg14, DW_OP_breg15, DW_OP_breg16,
103800b99b8Sopenharmony_ci    DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20,
104800b99b8Sopenharmony_ci    DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24,
105800b99b8Sopenharmony_ci    DW_OP_breg25, DW_OP_breg26, DW_OP_breg27, DW_OP_breg28,
106800b99b8Sopenharmony_ci    DW_OP_breg29, DW_OP_breg30, DW_OP_breg31,
107800b99b8Sopenharmony_ci    DW_OP_regx = 0x90,         // ULEB128 register
108800b99b8Sopenharmony_ci    DW_OP_fbreg,        // SLEB128 offset
109800b99b8Sopenharmony_ci    DW_OP_bregx,        // ULEB128 register, SLEB128 offset
110800b99b8Sopenharmony_ci    DW_OP_piece,        // ULEB128 size of piece
111800b99b8Sopenharmony_ci    DW_OP_deref_size,   // 1-byte size of data retrieved
112800b99b8Sopenharmony_ci    DW_OP_xderef_size,  // 1-byte size of data retrieved
113800b99b8Sopenharmony_ci    DW_OP_nop,
114800b99b8Sopenharmony_ci    DW_OP_push_object_address,
115800b99b8Sopenharmony_ci    DW_OP_call2,     // 2-byte offset of DIE
116800b99b8Sopenharmony_ci    DW_OP_call4,     // 4-byte offset of DIE
117800b99b8Sopenharmony_ci    DW_OP_call_ref,  // 4- or 8-byte offset of DIE
118800b99b8Sopenharmony_ci    // dwarf4 added
119800b99b8Sopenharmony_ci    DW_OP_form_tls_address,
120800b99b8Sopenharmony_ci    DW_OP_call_frame_cfa,
121800b99b8Sopenharmony_ci    DW_OP_bit_piece,       // ULEB128 size, ULEB128 offset
122800b99b8Sopenharmony_ci    DW_OP_implicit_value,  // ULEB128 size, block of that size
123800b99b8Sopenharmony_ci    DW_OP_stack_value,
124800b99b8Sopenharmony_ci    // dwarf5 added
125800b99b8Sopenharmony_ci    DW_OP_implicit_pointer,  // 4- or 8-byte offset of DIE, SLEB128 constant offset
126800b99b8Sopenharmony_ci    DW_OP_addrx,             // ULEB128 indirect address
127800b99b8Sopenharmony_ci    DW_OP_constx,            // ULEB128 indirect constant
128800b99b8Sopenharmony_ci    DW_OP_entry_value,       // ULEB128 size, block of that size
129800b99b8Sopenharmony_ci    DW_OP_const_type,        // ULEB128 type entry offset, 1-byte size, constant value
130800b99b8Sopenharmony_ci    DW_OP_regval_type,       // ULEB128 register number, ULEB128 constant offset
131800b99b8Sopenharmony_ci    DW_OP_deref_type,        // 1-byte size, ULEB128 type entry offset
132800b99b8Sopenharmony_ci    DW_OP_xderef_type,       // 1-byte size, ULEB128 type entry offset
133800b99b8Sopenharmony_ci    DW_OP_convert_type,      // ULEB128 type entry offset
134800b99b8Sopenharmony_ci    DW_OP_reinterpret_type,  // ULEB128 type entry offset
135800b99b8Sopenharmony_ci    DW_OP_lo_user = 0xe0,
136800b99b8Sopenharmony_ci    DW_OP_hi_user = 0xff
137800b99b8Sopenharmony_ci} DwarfOperater;
138800b99b8Sopenharmony_ci
139800b99b8Sopenharmony_ci// DWARF Call Frame Information
140800b99b8Sopenharmony_ci// Call frame instructions are encoded in one or more bytes. The primary opcode is
141800b99b8Sopenharmony_ci// encoded in the high order two bits of the first byte (that is, opcode = byte >> 6).
142800b99b8Sopenharmony_ci// An operand or extended opcode may be encoded in the low order 6 bits.
143800b99b8Sopenharmony_ci// Table 7.29: Call frame instruction encodings
144800b99b8Sopenharmony_citypedef enum {
145800b99b8Sopenharmony_ci    DW_CFA_advance_loc = 0x40,  // high 2-bits 0x1, low 6-bits delta
146800b99b8Sopenharmony_ci    DW_CFA_offset = 0x80,       // high 2-bits 0x2, low 6-bits register, ULEB128 offset
147800b99b8Sopenharmony_ci    DW_CFA_restore = 0xc0,      // high 2-bits 0x3, low 6-bits register
148800b99b8Sopenharmony_ci    // the value is the lower 6-bits, Operand1, Operand2
149800b99b8Sopenharmony_ci    DW_CFA_nop = 0x00,
150800b99b8Sopenharmony_ci    DW_CFA_set_loc,           // address
151800b99b8Sopenharmony_ci    DW_CFA_advance_loc1,      // 1-byte delta
152800b99b8Sopenharmony_ci    DW_CFA_advance_loc2,      // 2-byte delta
153800b99b8Sopenharmony_ci    DW_CFA_advance_loc4,      // 4-byte delta
154800b99b8Sopenharmony_ci    DW_CFA_offset_extended,   // ULEB128 register, ULEB128 offset
155800b99b8Sopenharmony_ci    DW_CFA_restore_extended,  // ULEB128 register
156800b99b8Sopenharmony_ci    DW_CFA_undefined,         // ULEB128 register
157800b99b8Sopenharmony_ci    DW_CFA_same_value,        // ULEB128 register
158800b99b8Sopenharmony_ci    DW_CFA_register,          // ULEB128 register, ULEB128 offset
159800b99b8Sopenharmony_ci    DW_CFA_remember_state,
160800b99b8Sopenharmony_ci    DW_CFA_restore_state,
161800b99b8Sopenharmony_ci    DW_CFA_def_cfa,             // ULEB128 register, ULEB128 offset
162800b99b8Sopenharmony_ci    DW_CFA_def_cfa_register,    // ULEB128 register
163800b99b8Sopenharmony_ci    DW_CFA_def_cfa_offset,      // ULEB128 offset
164800b99b8Sopenharmony_ci    DW_CFA_def_cfa_expression,  // BLOCK
165800b99b8Sopenharmony_ci    DW_CFA_expression = 0x10,   // ULEB128 register, BLOCK
166800b99b8Sopenharmony_ci    DW_CFA_offset_extended_sf,  // ULEB128 register, SLEB128 offset
167800b99b8Sopenharmony_ci    DW_CFA_def_cfa_sf,          // ULEB128 register, SLEB128 offset
168800b99b8Sopenharmony_ci    DW_CFA_def_cfa_offset_sf,   // SLEB128 offset
169800b99b8Sopenharmony_ci    DW_CFA_val_offset,          // ULEB128, ULEB128
170800b99b8Sopenharmony_ci    DW_CFA_val_offset_sf,       // ULEB128, SLEB128
171800b99b8Sopenharmony_ci    DW_CFA_val_expression,      // ULEB128, BLOCK
172800b99b8Sopenharmony_ci
173800b99b8Sopenharmony_ci    DW_CFA_lo_user = 0x1c,
174800b99b8Sopenharmony_ci    DW_CFA_AARCH64_negate_ra_state = 0x2d,
175800b99b8Sopenharmony_ci    // GNU extensions
176800b99b8Sopenharmony_ci    DW_CFA_GNU_args_size = 0x2e,
177800b99b8Sopenharmony_ci    DW_CFA_GNU_negative_offset_extended = 0x2f,
178800b99b8Sopenharmony_ci
179800b99b8Sopenharmony_ci    DW_CFA_hi_user = 0x3c,
180800b99b8Sopenharmony_ci} DwarfCfa;
181800b99b8Sopenharmony_ci
182800b99b8Sopenharmony_cienum DwarfEncoding : uint8_t {
183800b99b8Sopenharmony_ci    DW_EH_PE_omit = 0xff,
184800b99b8Sopenharmony_ci
185800b99b8Sopenharmony_ci    DW_EH_PE_absptr = 0x00,
186800b99b8Sopenharmony_ci    DW_EH_PE_uleb128 = 0x01,
187800b99b8Sopenharmony_ci    DW_EH_PE_udata2 = 0x02,
188800b99b8Sopenharmony_ci    DW_EH_PE_udata4 = 0x03,
189800b99b8Sopenharmony_ci    DW_EH_PE_udata8 = 0x04,
190800b99b8Sopenharmony_ci    DW_EH_PE_sleb128 = 0x09,
191800b99b8Sopenharmony_ci    DW_EH_PE_sdata2 = 0x0a,
192800b99b8Sopenharmony_ci    DW_EH_PE_sdata4 = 0x0b,
193800b99b8Sopenharmony_ci    DW_EH_PE_sdata8 = 0x0c,
194800b99b8Sopenharmony_ci
195800b99b8Sopenharmony_ci    DW_EH_PE_pcrel = 0x10,
196800b99b8Sopenharmony_ci    DW_EH_PE_textrel = 0x20,
197800b99b8Sopenharmony_ci    DW_EH_PE_datarel = 0x30,
198800b99b8Sopenharmony_ci    DW_EH_PE_funcrel = 0x40,
199800b99b8Sopenharmony_ci    DW_EH_PE_aligned = 0x50,
200800b99b8Sopenharmony_ci    DW_EH_PE_indirect = 0x80,
201800b99b8Sopenharmony_ci
202800b99b8Sopenharmony_ci    DW_EH_PE_udata1 = 0x0d,
203800b99b8Sopenharmony_ci    DW_EH_PE_sdata1 = 0x0e,
204800b99b8Sopenharmony_ci    DW_EH_PE_block = 0x0f,
205800b99b8Sopenharmony_ci};
206800b99b8Sopenharmony_ci
207800b99b8Sopenharmony_ci// we only need to parse eh_frame and eh_frame_hdr to get the dwarf-encoded unwind info
208800b99b8Sopenharmony_ci// https://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
209800b99b8Sopenharmony_ci// Parsed Common Information Entry Format
210800b99b8Sopenharmony_cistruct CommonInfoEntry {
211800b99b8Sopenharmony_ci    uint32_t codeAlignFactor = 0;
212800b99b8Sopenharmony_ci    int32_t dataAlignFactor = 0;
213800b99b8Sopenharmony_ci    uintptr_t returnAddressRegister = 0;
214800b99b8Sopenharmony_ci    bool hasAugmentationData = false;
215800b99b8Sopenharmony_ci    bool isSignalFrame = false;
216800b99b8Sopenharmony_ci    uint8_t segmentSize = 0;
217800b99b8Sopenharmony_ci    uintptr_t instructionsOff = 0;
218800b99b8Sopenharmony_ci    uintptr_t instructionsEnd = 0;
219800b99b8Sopenharmony_ci    // P
220800b99b8Sopenharmony_ci    uint8_t personality = 0;
221800b99b8Sopenharmony_ci    // L
222800b99b8Sopenharmony_ci    uint8_t lsdaEncoding = 0;
223800b99b8Sopenharmony_ci    // R
224800b99b8Sopenharmony_ci    uint8_t pointerEncoding = 0;
225800b99b8Sopenharmony_ci};
226800b99b8Sopenharmony_ci
227800b99b8Sopenharmony_ci// Parsed Frame Description Entry
228800b99b8Sopenharmony_ci// Table 8-3. Frame Description Entry Format
229800b99b8Sopenharmony_cistruct FrameDescEntry {
230800b99b8Sopenharmony_ci    uintptr_t pcStart = 0;
231800b99b8Sopenharmony_ci    uintptr_t pcEnd = 0;
232800b99b8Sopenharmony_ci    uintptr_t lsda = 0;
233800b99b8Sopenharmony_ci    uintptr_t instructionsOff = 0;
234800b99b8Sopenharmony_ci    uintptr_t instructionsEnd = 0;
235800b99b8Sopenharmony_ci    uintptr_t cieAddr = 0;
236800b99b8Sopenharmony_ci    CommonInfoEntry cie;
237800b99b8Sopenharmony_ci};
238800b99b8Sopenharmony_ci
239800b99b8Sopenharmony_cistruct DwarfTableEntry {
240800b99b8Sopenharmony_ci    int32_t startPc = 0;
241800b99b8Sopenharmony_ci    int32_t fdeOffset = 0;
242800b99b8Sopenharmony_ci};
243800b99b8Sopenharmony_ci
244800b99b8Sopenharmony_ci} // namespace HiviewDFX
245800b99b8Sopenharmony_ci} // namespace OHOS
246800b99b8Sopenharmony_ci#endif
247