1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker *
4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker *
8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker *
10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker */
16*eb293b8fSAndroid Build Coastguard Worker
17*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
18*eb293b8fSAndroid Build Coastguard Worker
19*eb293b8fSAndroid Build Coastguard Worker #include <string>
20*eb293b8fSAndroid Build Coastguard Worker
21*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfMemory.h>
22*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
23*eb293b8fSAndroid Build Coastguard Worker
24*eb293b8fSAndroid Build Coastguard Worker #include "Check.h"
25*eb293b8fSAndroid Build Coastguard Worker #include "DwarfEncoding.h"
26*eb293b8fSAndroid Build Coastguard Worker
27*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
28*eb293b8fSAndroid Build Coastguard Worker
ReadBytes(void * dst,size_t num_bytes)29*eb293b8fSAndroid Build Coastguard Worker bool DwarfMemory::ReadBytes(void* dst, size_t num_bytes) {
30*eb293b8fSAndroid Build Coastguard Worker if (!memory_->ReadFully(cur_offset_, dst, num_bytes)) {
31*eb293b8fSAndroid Build Coastguard Worker return false;
32*eb293b8fSAndroid Build Coastguard Worker }
33*eb293b8fSAndroid Build Coastguard Worker cur_offset_ += num_bytes;
34*eb293b8fSAndroid Build Coastguard Worker return true;
35*eb293b8fSAndroid Build Coastguard Worker }
36*eb293b8fSAndroid Build Coastguard Worker
37*eb293b8fSAndroid Build Coastguard Worker template <typename SignedType>
ReadSigned(uint64_t * value)38*eb293b8fSAndroid Build Coastguard Worker bool DwarfMemory::ReadSigned(uint64_t* value) {
39*eb293b8fSAndroid Build Coastguard Worker SignedType signed_value;
40*eb293b8fSAndroid Build Coastguard Worker if (!ReadBytes(&signed_value, sizeof(SignedType))) {
41*eb293b8fSAndroid Build Coastguard Worker return false;
42*eb293b8fSAndroid Build Coastguard Worker }
43*eb293b8fSAndroid Build Coastguard Worker *value = static_cast<int64_t>(signed_value);
44*eb293b8fSAndroid Build Coastguard Worker return true;
45*eb293b8fSAndroid Build Coastguard Worker }
46*eb293b8fSAndroid Build Coastguard Worker
ReadULEB128(uint64_t * value)47*eb293b8fSAndroid Build Coastguard Worker bool DwarfMemory::ReadULEB128(uint64_t* value) {
48*eb293b8fSAndroid Build Coastguard Worker uint64_t cur_value = 0;
49*eb293b8fSAndroid Build Coastguard Worker uint64_t shift = 0;
50*eb293b8fSAndroid Build Coastguard Worker uint8_t byte;
51*eb293b8fSAndroid Build Coastguard Worker do {
52*eb293b8fSAndroid Build Coastguard Worker if (!ReadBytes(&byte, 1)) {
53*eb293b8fSAndroid Build Coastguard Worker return false;
54*eb293b8fSAndroid Build Coastguard Worker }
55*eb293b8fSAndroid Build Coastguard Worker cur_value += static_cast<uint64_t>(byte & 0x7f) << shift;
56*eb293b8fSAndroid Build Coastguard Worker shift += 7;
57*eb293b8fSAndroid Build Coastguard Worker } while (byte & 0x80);
58*eb293b8fSAndroid Build Coastguard Worker *value = cur_value;
59*eb293b8fSAndroid Build Coastguard Worker return true;
60*eb293b8fSAndroid Build Coastguard Worker }
61*eb293b8fSAndroid Build Coastguard Worker
ReadSLEB128(int64_t * value)62*eb293b8fSAndroid Build Coastguard Worker bool DwarfMemory::ReadSLEB128(int64_t* value) {
63*eb293b8fSAndroid Build Coastguard Worker uint64_t cur_value = 0;
64*eb293b8fSAndroid Build Coastguard Worker uint64_t shift = 0;
65*eb293b8fSAndroid Build Coastguard Worker uint8_t byte;
66*eb293b8fSAndroid Build Coastguard Worker do {
67*eb293b8fSAndroid Build Coastguard Worker if (!ReadBytes(&byte, 1)) {
68*eb293b8fSAndroid Build Coastguard Worker return false;
69*eb293b8fSAndroid Build Coastguard Worker }
70*eb293b8fSAndroid Build Coastguard Worker cur_value += static_cast<uint64_t>(byte & 0x7f) << shift;
71*eb293b8fSAndroid Build Coastguard Worker shift += 7;
72*eb293b8fSAndroid Build Coastguard Worker } while (byte & 0x80);
73*eb293b8fSAndroid Build Coastguard Worker if (byte & 0x40) {
74*eb293b8fSAndroid Build Coastguard Worker // Negative value, need to sign extend.
75*eb293b8fSAndroid Build Coastguard Worker cur_value |= static_cast<uint64_t>(-1) << shift;
76*eb293b8fSAndroid Build Coastguard Worker }
77*eb293b8fSAndroid Build Coastguard Worker *value = static_cast<int64_t>(cur_value);
78*eb293b8fSAndroid Build Coastguard Worker return true;
79*eb293b8fSAndroid Build Coastguard Worker }
80*eb293b8fSAndroid Build Coastguard Worker
81*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
GetEncodedSize(uint8_t encoding)82*eb293b8fSAndroid Build Coastguard Worker size_t DwarfMemory::GetEncodedSize(uint8_t encoding) {
83*eb293b8fSAndroid Build Coastguard Worker switch (encoding & 0x0f) {
84*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_absptr:
85*eb293b8fSAndroid Build Coastguard Worker return sizeof(AddressType);
86*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_udata1:
87*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sdata1:
88*eb293b8fSAndroid Build Coastguard Worker return 1;
89*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_udata2:
90*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sdata2:
91*eb293b8fSAndroid Build Coastguard Worker return 2;
92*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_udata4:
93*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sdata4:
94*eb293b8fSAndroid Build Coastguard Worker return 4;
95*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_udata8:
96*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sdata8:
97*eb293b8fSAndroid Build Coastguard Worker return 8;
98*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_uleb128:
99*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sleb128:
100*eb293b8fSAndroid Build Coastguard Worker default:
101*eb293b8fSAndroid Build Coastguard Worker return 0;
102*eb293b8fSAndroid Build Coastguard Worker }
103*eb293b8fSAndroid Build Coastguard Worker }
104*eb293b8fSAndroid Build Coastguard Worker
AdjustEncodedValue(uint8_t encoding,uint64_t * value)105*eb293b8fSAndroid Build Coastguard Worker bool DwarfMemory::AdjustEncodedValue(uint8_t encoding, uint64_t* value) {
106*eb293b8fSAndroid Build Coastguard Worker CHECK((encoding & 0x0f) == 0);
107*eb293b8fSAndroid Build Coastguard Worker
108*eb293b8fSAndroid Build Coastguard Worker // Handle the encoding.
109*eb293b8fSAndroid Build Coastguard Worker switch (encoding) {
110*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_absptr:
111*eb293b8fSAndroid Build Coastguard Worker // Nothing to do.
112*eb293b8fSAndroid Build Coastguard Worker break;
113*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_pcrel:
114*eb293b8fSAndroid Build Coastguard Worker if (pc_offset_ == INT64_MAX) {
115*eb293b8fSAndroid Build Coastguard Worker // Unsupported encoding.
116*eb293b8fSAndroid Build Coastguard Worker return false;
117*eb293b8fSAndroid Build Coastguard Worker }
118*eb293b8fSAndroid Build Coastguard Worker *value += pc_offset_;
119*eb293b8fSAndroid Build Coastguard Worker break;
120*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_textrel:
121*eb293b8fSAndroid Build Coastguard Worker if (text_offset_ == static_cast<uint64_t>(-1)) {
122*eb293b8fSAndroid Build Coastguard Worker // Unsupported encoding.
123*eb293b8fSAndroid Build Coastguard Worker return false;
124*eb293b8fSAndroid Build Coastguard Worker }
125*eb293b8fSAndroid Build Coastguard Worker *value += text_offset_;
126*eb293b8fSAndroid Build Coastguard Worker break;
127*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_datarel:
128*eb293b8fSAndroid Build Coastguard Worker if (data_offset_ == static_cast<uint64_t>(-1)) {
129*eb293b8fSAndroid Build Coastguard Worker // Unsupported encoding.
130*eb293b8fSAndroid Build Coastguard Worker return false;
131*eb293b8fSAndroid Build Coastguard Worker }
132*eb293b8fSAndroid Build Coastguard Worker *value += data_offset_;
133*eb293b8fSAndroid Build Coastguard Worker break;
134*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_funcrel:
135*eb293b8fSAndroid Build Coastguard Worker if (func_offset_ == static_cast<uint64_t>(-1)) {
136*eb293b8fSAndroid Build Coastguard Worker // Unsupported encoding.
137*eb293b8fSAndroid Build Coastguard Worker return false;
138*eb293b8fSAndroid Build Coastguard Worker }
139*eb293b8fSAndroid Build Coastguard Worker *value += func_offset_;
140*eb293b8fSAndroid Build Coastguard Worker break;
141*eb293b8fSAndroid Build Coastguard Worker default:
142*eb293b8fSAndroid Build Coastguard Worker return false;
143*eb293b8fSAndroid Build Coastguard Worker }
144*eb293b8fSAndroid Build Coastguard Worker
145*eb293b8fSAndroid Build Coastguard Worker return true;
146*eb293b8fSAndroid Build Coastguard Worker }
147*eb293b8fSAndroid Build Coastguard Worker
148*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
ReadEncodedValue(uint8_t encoding,uint64_t * value)149*eb293b8fSAndroid Build Coastguard Worker bool DwarfMemory::ReadEncodedValue(uint8_t encoding, uint64_t* value) {
150*eb293b8fSAndroid Build Coastguard Worker if (encoding == DW_EH_PE_omit) {
151*eb293b8fSAndroid Build Coastguard Worker *value = 0;
152*eb293b8fSAndroid Build Coastguard Worker return true;
153*eb293b8fSAndroid Build Coastguard Worker } else if (encoding == DW_EH_PE_aligned) {
154*eb293b8fSAndroid Build Coastguard Worker if (__builtin_add_overflow(cur_offset_, sizeof(AddressType) - 1, &cur_offset_)) {
155*eb293b8fSAndroid Build Coastguard Worker return false;
156*eb293b8fSAndroid Build Coastguard Worker }
157*eb293b8fSAndroid Build Coastguard Worker cur_offset_ &= -sizeof(AddressType);
158*eb293b8fSAndroid Build Coastguard Worker
159*eb293b8fSAndroid Build Coastguard Worker if (sizeof(AddressType) != sizeof(uint64_t)) {
160*eb293b8fSAndroid Build Coastguard Worker *value = 0;
161*eb293b8fSAndroid Build Coastguard Worker }
162*eb293b8fSAndroid Build Coastguard Worker return ReadBytes(value, sizeof(AddressType));
163*eb293b8fSAndroid Build Coastguard Worker }
164*eb293b8fSAndroid Build Coastguard Worker
165*eb293b8fSAndroid Build Coastguard Worker // Get the data.
166*eb293b8fSAndroid Build Coastguard Worker switch (encoding & 0x0f) {
167*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_absptr:
168*eb293b8fSAndroid Build Coastguard Worker if (sizeof(AddressType) != sizeof(uint64_t)) {
169*eb293b8fSAndroid Build Coastguard Worker *value = 0;
170*eb293b8fSAndroid Build Coastguard Worker }
171*eb293b8fSAndroid Build Coastguard Worker if (!ReadBytes(value, sizeof(AddressType))) {
172*eb293b8fSAndroid Build Coastguard Worker return false;
173*eb293b8fSAndroid Build Coastguard Worker }
174*eb293b8fSAndroid Build Coastguard Worker break;
175*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_uleb128:
176*eb293b8fSAndroid Build Coastguard Worker if (!ReadULEB128(value)) {
177*eb293b8fSAndroid Build Coastguard Worker return false;
178*eb293b8fSAndroid Build Coastguard Worker }
179*eb293b8fSAndroid Build Coastguard Worker break;
180*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sleb128:
181*eb293b8fSAndroid Build Coastguard Worker int64_t signed_value;
182*eb293b8fSAndroid Build Coastguard Worker if (!ReadSLEB128(&signed_value)) {
183*eb293b8fSAndroid Build Coastguard Worker return false;
184*eb293b8fSAndroid Build Coastguard Worker }
185*eb293b8fSAndroid Build Coastguard Worker *value = static_cast<uint64_t>(signed_value);
186*eb293b8fSAndroid Build Coastguard Worker break;
187*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_udata1: {
188*eb293b8fSAndroid Build Coastguard Worker uint8_t value8;
189*eb293b8fSAndroid Build Coastguard Worker if (!ReadBytes(&value8, 1)) {
190*eb293b8fSAndroid Build Coastguard Worker return false;
191*eb293b8fSAndroid Build Coastguard Worker }
192*eb293b8fSAndroid Build Coastguard Worker *value = value8;
193*eb293b8fSAndroid Build Coastguard Worker } break;
194*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sdata1:
195*eb293b8fSAndroid Build Coastguard Worker if (!ReadSigned<int8_t>(value)) {
196*eb293b8fSAndroid Build Coastguard Worker return false;
197*eb293b8fSAndroid Build Coastguard Worker }
198*eb293b8fSAndroid Build Coastguard Worker break;
199*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_udata2: {
200*eb293b8fSAndroid Build Coastguard Worker uint16_t value16;
201*eb293b8fSAndroid Build Coastguard Worker if (!ReadBytes(&value16, 2)) {
202*eb293b8fSAndroid Build Coastguard Worker return false;
203*eb293b8fSAndroid Build Coastguard Worker }
204*eb293b8fSAndroid Build Coastguard Worker *value = value16;
205*eb293b8fSAndroid Build Coastguard Worker } break;
206*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sdata2:
207*eb293b8fSAndroid Build Coastguard Worker if (!ReadSigned<int16_t>(value)) {
208*eb293b8fSAndroid Build Coastguard Worker return false;
209*eb293b8fSAndroid Build Coastguard Worker }
210*eb293b8fSAndroid Build Coastguard Worker break;
211*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_udata4: {
212*eb293b8fSAndroid Build Coastguard Worker uint32_t value32;
213*eb293b8fSAndroid Build Coastguard Worker if (!ReadBytes(&value32, 4)) {
214*eb293b8fSAndroid Build Coastguard Worker return false;
215*eb293b8fSAndroid Build Coastguard Worker }
216*eb293b8fSAndroid Build Coastguard Worker *value = value32;
217*eb293b8fSAndroid Build Coastguard Worker } break;
218*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sdata4:
219*eb293b8fSAndroid Build Coastguard Worker if (!ReadSigned<int32_t>(value)) {
220*eb293b8fSAndroid Build Coastguard Worker return false;
221*eb293b8fSAndroid Build Coastguard Worker }
222*eb293b8fSAndroid Build Coastguard Worker break;
223*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_udata8:
224*eb293b8fSAndroid Build Coastguard Worker if (!ReadBytes(value, sizeof(uint64_t))) {
225*eb293b8fSAndroid Build Coastguard Worker return false;
226*eb293b8fSAndroid Build Coastguard Worker }
227*eb293b8fSAndroid Build Coastguard Worker break;
228*eb293b8fSAndroid Build Coastguard Worker case DW_EH_PE_sdata8:
229*eb293b8fSAndroid Build Coastguard Worker if (!ReadSigned<int64_t>(value)) {
230*eb293b8fSAndroid Build Coastguard Worker return false;
231*eb293b8fSAndroid Build Coastguard Worker }
232*eb293b8fSAndroid Build Coastguard Worker break;
233*eb293b8fSAndroid Build Coastguard Worker default:
234*eb293b8fSAndroid Build Coastguard Worker return false;
235*eb293b8fSAndroid Build Coastguard Worker }
236*eb293b8fSAndroid Build Coastguard Worker
237*eb293b8fSAndroid Build Coastguard Worker return AdjustEncodedValue(encoding & 0x70, value);
238*eb293b8fSAndroid Build Coastguard Worker }
239*eb293b8fSAndroid Build Coastguard Worker
240*eb293b8fSAndroid Build Coastguard Worker // Instantiate all of the needed template functions.
241*eb293b8fSAndroid Build Coastguard Worker template bool DwarfMemory::ReadSigned<int8_t>(uint64_t*);
242*eb293b8fSAndroid Build Coastguard Worker template bool DwarfMemory::ReadSigned<int16_t>(uint64_t*);
243*eb293b8fSAndroid Build Coastguard Worker template bool DwarfMemory::ReadSigned<int32_t>(uint64_t*);
244*eb293b8fSAndroid Build Coastguard Worker template bool DwarfMemory::ReadSigned<int64_t>(uint64_t*);
245*eb293b8fSAndroid Build Coastguard Worker
246*eb293b8fSAndroid Build Coastguard Worker template size_t DwarfMemory::GetEncodedSize<uint32_t>(uint8_t);
247*eb293b8fSAndroid Build Coastguard Worker template size_t DwarfMemory::GetEncodedSize<uint64_t>(uint8_t);
248*eb293b8fSAndroid Build Coastguard Worker
249*eb293b8fSAndroid Build Coastguard Worker template bool DwarfMemory::ReadEncodedValue<uint32_t>(uint8_t, uint64_t*);
250*eb293b8fSAndroid Build Coastguard Worker template bool DwarfMemory::ReadEncodedValue<uint64_t>(uint8_t, uint64_t*);
251*eb293b8fSAndroid Build Coastguard Worker
252*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack
253