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