1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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_ENCODING_H
16#define DWARF_ENCODING_H
17
18#include "utilities.h"
19
20// now we only support 64 bit.
21using uleb128_t = uint64_t;
22using sleb128_t = int64_t;
23
24namespace OHOS {
25namespace Developtools {
26namespace NativeDaemon {
27static constexpr const int LEB_BYTE_EFFECTIVE_LENGTH = 7;
28static constexpr const int SIGN_BIT_OF_BYTE = 0x40;
29static constexpr const int MAX_VALUE_OF_BYTE = 0x7f;
30static constexpr const int MORE_BIT_OF_BYTE = 0x80;
31
32/*
3310.5.1. DWARF Exception Header Encoding
34The DWARF Exception Header Encoding is used to describe the type of data used in the .eh_frame and
35.eh_frame_hdr section. The upper 4 bits indicate how the value is to be applied. The lower 4 bits
36indicate the format of the data.
37using dw_encode_t = unsigned char; // 4 bits + 4 bits
38*/
39
40using dw_encode_t = unsigned char; // 4 bits + 4 bits
41
42// Table 10-5. DWARF Exception Header value format
43
44enum DW_EH_PE_VF {
45    DW_EH_PE_absptr = 0x00,  // a literal pointer whose size is determined by the architecture.
46    DW_EH_PE_uleb128 = 0x01, // Unsigned value is encoded using the Little Endian Base 128 (LEB128)
47    DW_EH_PE_udata2 = 0x02,  // A 2 bytes unsigned value.
48    DW_EH_PE_udata4 = 0x03,  // A 4 bytes unsigned value.
49    DW_EH_PE_udata8 = 0x04,  // An 8 bytes unsigned value.
50    DW_EH_PE_sleb128 = 0x09, // Signed value is encoded using the Little Endian Base 128(LEB128)
51    DW_EH_PE_sdata2 = 0x0A,  // A 2 bytes signed value.
52    DW_EH_PE_sdata4 = 0x0B,  // A 4 bytes signed value.
53    DW_EH_PE_sdata8 = 0x0C,  // An 8 bytes signed value.
54};
55
56// Table 10-6. DWARF Exception Header application
57enum DW_EH_PE_A {
58    DW_EH_PE_nothing = 0x00, // nothing to do
59    DW_EH_PE_pcrel = 0x10,   // relative to the current program counter.
60    DW_EH_PE_textrel = 0x20, // relative to the beginning of the .text section.
61    DW_EH_PE_datarel = 0x30, // relative to the beginning of the .got or .eh_frame_hdr section.
62    DW_EH_PE_funcrel = 0x40, // relative to the beginning of the function.
63    DW_EH_PE_aligned = 0x50, // aligned to an address unit sized boundary.
64    DW_EH_PE_omit = 0xff,    // indicate that no value ispresent.
65};
66
67const std::map<dw_encode_t, size_t> DWFormatSizeMap = {
68#ifdef ARM
69    {DW_EH_PE_absptr, 4},
70#else
71    {DW_EH_PE_absptr, 8},
72#endif
73#ifdef NOT_USE
74    {DW_EH_PE_uleb128, sizeof(char) * 128},
75#endif
76    {DW_EH_PE_udata2, sizeof(char) * 2},
77    {DW_EH_PE_udata4, sizeof(char) * 4},
78    {DW_EH_PE_udata8, sizeof(char) * 8},
79#ifdef NOT_USE
80    {DW_EH_PE_sleb128, sizeof(char) * 128},
81#endif
82    {DW_EH_PE_sdata2, sizeof(char) * 2},
83    {DW_EH_PE_sdata4, sizeof(char) * 4},
84    {DW_EH_PE_sdata8, sizeof(char) * 8},
85};
86
87template<class T>
88uint64_t dwReadAnyTypeData(const unsigned char *&buffer, T)
89{
90    T value;
91    if (memcpy_s(&value, sizeof(T), buffer, sizeof(T)) != EOK) {
92        return 0;
93    }
94    buffer += sizeof(T);
95    return static_cast<uint64_t>(value);
96}
97
98class DwarfEncoding {
99public:
100    DwarfEncoding(dw_encode_t dw, const unsigned char *&data, uint64_t vaddrBase = 0,
101                  uint64_t vaddrPC = 0, uint64_t vaddrText = 0);
102
103    const std::string ToString() const;
104
105    const unsigned char *GetEnd() const;
106
107    const unsigned char *GetData() const;
108
109    size_t GetSize() const;
110
111    uint64_t GetValue() const;
112
113    uint64_t GetAppliedValue() const;
114
115    bool IsOmit() const;
116
117private:
118    dw_encode_t dw_;
119    const unsigned char *data_;
120    uint64_t vaddrBase_ = 0;
121    uint64_t vaddrPC_ = 0;
122    uint64_t vaddrText_ = 0;
123    uint64_t value_[2] = {0, 0};
124
125    dw_encode_t Format() const;
126
127    dw_encode_t Application() const;
128
129    uint64_t ReadValue(const unsigned char *&data) const;
130
131    const std::string FormatName() const;
132
133    const std::string ApplicationName() const;
134};
135
136/*
137Linux Standard Base Core Specification 4.1
138Chapter 10. Object Format
13910.6.2. The .eh_frame_hdr section
140
141Table 10-11. .eh_frame_hdr Section Format
142
143Encoding	Field
144unsigned byte	version
145unsigned byte	eh_frame_ptr_enc
146unsigned byte	fde_count_enc
147unsigned byte	table_enc
148encoded	eh_frame_ptr
149encoded	fde_count
150    binary search table
151*/
152
153struct binary_search_table {
154    uint64_t ipVaddrOffset;
155    uint64_t fdeVaddrOffset;
156};
157
158struct eh_frame_hdr {
159    // Version of the .eh_frame_hdr format. This value shall be 1.
160    dw_encode_t version;
161
162    // The encoding format of the eh_frame_ptr field.
163    dw_encode_t eh_frame_ptr_enc;
164
165    // The encoding format of the fde_count field. A value of DW_EH_PE_omit indicates the binary
166    // search table is not present.
167    dw_encode_t fde_count_enc;
168
169    // The encoding format of the entries in the binary search table. A value of DW_EH_PE_omit
170    // indicates the binary search table is not present.
171    dw_encode_t table_enc;
172
173    // The encoded value of the pointer to the start of the .eh_frame section.
174    /*
175    dw_encode_t eh_frame_ptr
176    dw_encode_t fde_count
177    */
178    // A binary search table containing fde_count entries. Each entry of the table consist of two
179    // encoded values, the initial location, and the address. The entries are sorted in an
180    // increasing order by the initial location value.
181
182    /*
183     * struct {
184     *    encoded start_ip
185     *    encoded fde_addr
186     * } binary_search_table[fde_count]
187     */
188    unsigned char encode_data[0];
189} PACKED;
190} // namespace NativeDaemon
191} // namespace Developtools
192} // namespace OHOS
193#endif
194