/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Support/ARMAttributeParser.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- ARMAttributeParser.cpp - ARM Attribute Information Printer -------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "llvm/Support/ARMAttributeParser.h" |
10 | | #include "llvm/ADT/STLExtras.h" |
11 | | #include "llvm/ADT/StringExtras.h" |
12 | | #include "llvm/Support/LEB128.h" |
13 | | #include "llvm/Support/ScopedPrinter.h" |
14 | | |
15 | | using namespace llvm; |
16 | | using namespace llvm::ARMBuildAttrs; |
17 | | |
18 | | |
19 | | static const EnumEntry<unsigned> TagNames[] = { |
20 | | { "Tag_File", ARMBuildAttrs::File }, |
21 | | { "Tag_Section", ARMBuildAttrs::Section }, |
22 | | { "Tag_Symbol", ARMBuildAttrs::Symbol }, |
23 | | }; |
24 | | |
25 | | namespace llvm { |
26 | | #define ATTRIBUTE_HANDLER(Attr_) \ |
27 | | { ARMBuildAttrs::Attr_, &ARMAttributeParser::Attr_ } |
28 | | |
29 | | const ARMAttributeParser::DisplayHandler |
30 | | ARMAttributeParser::DisplayRoutines[] = { |
31 | | { ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::StringAttribute, }, |
32 | | { ARMBuildAttrs::CPU_name, &ARMAttributeParser::StringAttribute }, |
33 | | ATTRIBUTE_HANDLER(CPU_arch), |
34 | | ATTRIBUTE_HANDLER(CPU_arch_profile), |
35 | | ATTRIBUTE_HANDLER(ARM_ISA_use), |
36 | | ATTRIBUTE_HANDLER(THUMB_ISA_use), |
37 | | ATTRIBUTE_HANDLER(FP_arch), |
38 | | ATTRIBUTE_HANDLER(WMMX_arch), |
39 | | ATTRIBUTE_HANDLER(Advanced_SIMD_arch), |
40 | | ATTRIBUTE_HANDLER(MVE_arch), |
41 | | ATTRIBUTE_HANDLER(PCS_config), |
42 | | ATTRIBUTE_HANDLER(ABI_PCS_R9_use), |
43 | | ATTRIBUTE_HANDLER(ABI_PCS_RW_data), |
44 | | ATTRIBUTE_HANDLER(ABI_PCS_RO_data), |
45 | | ATTRIBUTE_HANDLER(ABI_PCS_GOT_use), |
46 | | ATTRIBUTE_HANDLER(ABI_PCS_wchar_t), |
47 | | ATTRIBUTE_HANDLER(ABI_FP_rounding), |
48 | | ATTRIBUTE_HANDLER(ABI_FP_denormal), |
49 | | ATTRIBUTE_HANDLER(ABI_FP_exceptions), |
50 | | ATTRIBUTE_HANDLER(ABI_FP_user_exceptions), |
51 | | ATTRIBUTE_HANDLER(ABI_FP_number_model), |
52 | | ATTRIBUTE_HANDLER(ABI_align_needed), |
53 | | ATTRIBUTE_HANDLER(ABI_align_preserved), |
54 | | ATTRIBUTE_HANDLER(ABI_enum_size), |
55 | | ATTRIBUTE_HANDLER(ABI_HardFP_use), |
56 | | ATTRIBUTE_HANDLER(ABI_VFP_args), |
57 | | ATTRIBUTE_HANDLER(ABI_WMMX_args), |
58 | | ATTRIBUTE_HANDLER(ABI_optimization_goals), |
59 | | ATTRIBUTE_HANDLER(ABI_FP_optimization_goals), |
60 | | ATTRIBUTE_HANDLER(compatibility), |
61 | | ATTRIBUTE_HANDLER(CPU_unaligned_access), |
62 | | ATTRIBUTE_HANDLER(FP_HP_extension), |
63 | | ATTRIBUTE_HANDLER(ABI_FP_16bit_format), |
64 | | ATTRIBUTE_HANDLER(MPextension_use), |
65 | | ATTRIBUTE_HANDLER(DIV_use), |
66 | | ATTRIBUTE_HANDLER(DSP_extension), |
67 | | ATTRIBUTE_HANDLER(T2EE_use), |
68 | | ATTRIBUTE_HANDLER(Virtualization_use), |
69 | | ATTRIBUTE_HANDLER(nodefaults) |
70 | | }; |
71 | | |
72 | | #undef ATTRIBUTE_HANDLER |
73 | | |
74 | | uint64_t ARMAttributeParser::ParseInteger(const uint8_t *Data, |
75 | 2.93k | uint32_t &Offset) { |
76 | 2.93k | unsigned Length; |
77 | 2.93k | uint64_t Value = decodeULEB128(Data + Offset, &Length); |
78 | 2.93k | Offset = Offset + Length; |
79 | 2.93k | return Value; |
80 | 2.93k | } |
81 | | |
82 | | StringRef ARMAttributeParser::ParseString(const uint8_t *Data, |
83 | 187 | uint32_t &Offset) { |
84 | 187 | const char *String = reinterpret_cast<const char*>(Data + Offset); |
85 | 187 | size_t Length = std::strlen(String); |
86 | 187 | Offset = Offset + Length + 1; |
87 | 187 | return StringRef(String, Length); |
88 | 187 | } |
89 | | |
90 | | void ARMAttributeParser::IntegerAttribute(AttrType Tag, const uint8_t *Data, |
91 | 0 | uint32_t &Offset) { |
92 | 0 |
|
93 | 0 | uint64_t Value = ParseInteger(Data, Offset); |
94 | 0 | Attributes.insert(std::make_pair(Tag, Value)); |
95 | 0 |
|
96 | 0 | if (SW) |
97 | 0 | SW->printNumber(ARMBuildAttrs::AttrTypeAsString(Tag), Value); |
98 | 0 | } |
99 | | |
100 | | void ARMAttributeParser::StringAttribute(AttrType Tag, const uint8_t *Data, |
101 | 180 | uint32_t &Offset) { |
102 | 180 | StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false); |
103 | 180 | StringRef ValueDesc = ParseString(Data, Offset); |
104 | 180 | |
105 | 180 | if (SW) { |
106 | 72 | DictScope AS(*SW, "Attribute"); |
107 | 72 | SW->printNumber("Tag", Tag); |
108 | 72 | if (!TagName.empty()) |
109 | 72 | SW->printString("TagName", TagName); |
110 | 72 | SW->printString("Value", ValueDesc); |
111 | 72 | } |
112 | 180 | } |
113 | | |
114 | | void ARMAttributeParser::PrintAttribute(unsigned Tag, unsigned Value, |
115 | 2.92k | StringRef ValueDesc) { |
116 | 2.92k | Attributes.insert(std::make_pair(Tag, Value)); |
117 | 2.92k | |
118 | 2.92k | if (SW) { |
119 | 649 | StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, |
120 | 649 | /*TagPrefix*/false); |
121 | 649 | DictScope AS(*SW, "Attribute"); |
122 | 649 | SW->printNumber("Tag", Tag); |
123 | 649 | SW->printNumber("Value", Value); |
124 | 649 | if (!TagName.empty()) |
125 | 649 | SW->printString("TagName", TagName); |
126 | 649 | if (!ValueDesc.empty()) |
127 | 649 | SW->printString("Description", ValueDesc); |
128 | 649 | } |
129 | 2.92k | } |
130 | | |
131 | | void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data, |
132 | 339 | uint32_t &Offset) { |
133 | 339 | static const char *const Strings[] = { |
134 | 339 | "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6", |
135 | 339 | "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M", |
136 | 339 | "ARM v7E-M", "ARM v8", nullptr, |
137 | 339 | "ARM v8-M Baseline", "ARM v8-M Mainline", nullptr, nullptr, nullptr, |
138 | 339 | "ARM v8.1-M Mainline" |
139 | 339 | }; |
140 | 339 | |
141 | 339 | uint64_t Value = ParseInteger(Data, Offset); |
142 | 339 | StringRef ValueDesc = |
143 | 339 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
144 | 339 | PrintAttribute(Tag, Value, ValueDesc); |
145 | 339 | } |
146 | | |
147 | | void ARMAttributeParser::CPU_arch_profile(AttrType Tag, const uint8_t *Data, |
148 | 258 | uint32_t &Offset) { |
149 | 258 | uint64_t Encoded = ParseInteger(Data, Offset); |
150 | 258 | |
151 | 258 | StringRef Profile; |
152 | 258 | switch (Encoded) { |
153 | 258 | default: Profile = "Unknown"; break0 ; |
154 | 258 | case 'A': Profile = "Application"; break234 ; |
155 | 258 | case 'R': Profile = "Real-time"; break6 ; |
156 | 258 | case 'M': Profile = "Microcontroller"; break15 ; |
157 | 258 | case 'S': Profile = "Classic"; break2 ; |
158 | 258 | case 0: Profile = "None"; break1 ; |
159 | 258 | } |
160 | 258 | |
161 | 258 | PrintAttribute(Tag, Encoded, Profile); |
162 | 258 | } |
163 | | |
164 | | void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data, |
165 | 294 | uint32_t &Offset) { |
166 | 294 | static const char *const Strings[] = { "Not Permitted", "Permitted" }; |
167 | 294 | |
168 | 294 | uint64_t Value = ParseInteger(Data, Offset); |
169 | 294 | StringRef ValueDesc = |
170 | 294 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
171 | 294 | PrintAttribute(Tag, Value, ValueDesc); |
172 | 294 | } |
173 | | |
174 | | void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data, |
175 | 296 | uint32_t &Offset) { |
176 | 296 | static const char *const Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" }; |
177 | 296 | |
178 | 296 | uint64_t Value = ParseInteger(Data, Offset); |
179 | 296 | StringRef ValueDesc = |
180 | 296 | (Value < array_lengthof(Strings)) ? Strings[Value]295 : nullptr1 ; |
181 | 296 | PrintAttribute(Tag, Value, ValueDesc); |
182 | 296 | } |
183 | | |
184 | | void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data, |
185 | 219 | uint32_t &Offset) { |
186 | 219 | static const char *const Strings[] = { |
187 | 219 | "Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4", |
188 | 219 | "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16" |
189 | 219 | }; |
190 | 219 | |
191 | 219 | uint64_t Value = ParseInteger(Data, Offset); |
192 | 219 | StringRef ValueDesc = |
193 | 219 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
194 | 219 | PrintAttribute(Tag, Value, ValueDesc); |
195 | 219 | } |
196 | | |
197 | | void ARMAttributeParser::WMMX_arch(AttrType Tag, const uint8_t *Data, |
198 | 9 | uint32_t &Offset) { |
199 | 9 | static const char *const Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" }; |
200 | 9 | |
201 | 9 | uint64_t Value = ParseInteger(Data, Offset); |
202 | 9 | StringRef ValueDesc = |
203 | 9 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
204 | 9 | PrintAttribute(Tag, Value, ValueDesc); |
205 | 9 | } |
206 | | |
207 | | void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data, |
208 | 197 | uint32_t &Offset) { |
209 | 197 | static const char *const Strings[] = { |
210 | 197 | "Not Permitted", "NEONv1", "NEONv2+FMA", "ARMv8-a NEON", "ARMv8.1-a NEON" |
211 | 197 | }; |
212 | 197 | |
213 | 197 | uint64_t Value = ParseInteger(Data, Offset); |
214 | 197 | StringRef ValueDesc = |
215 | 197 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
216 | 197 | PrintAttribute(Tag, Value, ValueDesc); |
217 | 197 | } |
218 | | |
219 | | void ARMAttributeParser::MVE_arch(AttrType Tag, const uint8_t *Data, |
220 | 3 | uint32_t &Offset) { |
221 | 3 | static const char *const Strings[] = { |
222 | 3 | "Not Permitted", "MVE integer", "MVE integer and float" |
223 | 3 | }; |
224 | 3 | |
225 | 3 | uint64_t Value = ParseInteger(Data, Offset); |
226 | 3 | StringRef ValueDesc = |
227 | 3 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
228 | 3 | PrintAttribute(Tag, Value, ValueDesc); |
229 | 3 | } |
230 | | |
231 | | void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data, |
232 | 17 | uint32_t &Offset) { |
233 | 17 | static const char *const Strings[] = { |
234 | 17 | "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004", |
235 | 17 | "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)" |
236 | 17 | }; |
237 | 17 | |
238 | 17 | uint64_t Value = ParseInteger(Data, Offset); |
239 | 17 | StringRef ValueDesc = |
240 | 17 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
241 | 17 | PrintAttribute(Tag, Value, ValueDesc); |
242 | 17 | } |
243 | | |
244 | | void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data, |
245 | 56 | uint32_t &Offset) { |
246 | 56 | static const char *const Strings[] = { "v6", "Static Base", "TLS", "Unused" }; |
247 | 56 | |
248 | 56 | uint64_t Value = ParseInteger(Data, Offset); |
249 | 56 | StringRef ValueDesc = |
250 | 56 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
251 | 56 | PrintAttribute(Tag, Value, ValueDesc); |
252 | 56 | } |
253 | | |
254 | | void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data, |
255 | 18 | uint32_t &Offset) { |
256 | 18 | static const char *const Strings[] = { |
257 | 18 | "Absolute", "PC-relative", "SB-relative", "Not Permitted" |
258 | 18 | }; |
259 | 18 | |
260 | 18 | uint64_t Value = ParseInteger(Data, Offset); |
261 | 18 | StringRef ValueDesc = |
262 | 18 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
263 | 18 | PrintAttribute(Tag, Value, ValueDesc); |
264 | 18 | } |
265 | | |
266 | | void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data, |
267 | 16 | uint32_t &Offset) { |
268 | 16 | static const char *const Strings[] = { |
269 | 16 | "Absolute", "PC-relative", "Not Permitted" |
270 | 16 | }; |
271 | 16 | |
272 | 16 | uint64_t Value = ParseInteger(Data, Offset); |
273 | 16 | StringRef ValueDesc = |
274 | 16 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
275 | 16 | PrintAttribute(Tag, Value, ValueDesc); |
276 | 16 | } |
277 | | |
278 | | void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data, |
279 | 54 | uint32_t &Offset) { |
280 | 54 | static const char *const Strings[] = { |
281 | 54 | "Not Permitted", "Direct", "GOT-Indirect" |
282 | 54 | }; |
283 | 54 | |
284 | 54 | uint64_t Value = ParseInteger(Data, Offset); |
285 | 54 | StringRef ValueDesc = |
286 | 54 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
287 | 54 | PrintAttribute(Tag, Value, ValueDesc); |
288 | 54 | } |
289 | | |
290 | | void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data, |
291 | 51 | uint32_t &Offset) { |
292 | 51 | static const char *const Strings[] = { |
293 | 51 | "Not Permitted", "Unknown", "2-byte", "Unknown", "4-byte" |
294 | 51 | }; |
295 | 51 | |
296 | 51 | uint64_t Value = ParseInteger(Data, Offset); |
297 | 51 | StringRef ValueDesc = |
298 | 51 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
299 | 51 | PrintAttribute(Tag, Value, ValueDesc); |
300 | 51 | } |
301 | | |
302 | | void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data, |
303 | 5 | uint32_t &Offset) { |
304 | 5 | static const char *const Strings[] = { "IEEE-754", "Runtime" }; |
305 | 5 | |
306 | 5 | uint64_t Value = ParseInteger(Data, Offset); |
307 | 5 | StringRef ValueDesc = |
308 | 5 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
309 | 5 | PrintAttribute(Tag, Value, ValueDesc); |
310 | 5 | } |
311 | | |
312 | | void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data, |
313 | 89 | uint32_t &Offset) { |
314 | 89 | static const char *const Strings[] = { |
315 | 89 | "Unsupported", "IEEE-754", "Sign Only" |
316 | 89 | }; |
317 | 89 | |
318 | 89 | uint64_t Value = ParseInteger(Data, Offset); |
319 | 89 | StringRef ValueDesc = |
320 | 89 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
321 | 89 | PrintAttribute(Tag, Value, ValueDesc); |
322 | 89 | } |
323 | | |
324 | | void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data, |
325 | 87 | uint32_t &Offset) { |
326 | 87 | static const char *const Strings[] = { "Not Permitted", "IEEE-754" }; |
327 | 87 | |
328 | 87 | uint64_t Value = ParseInteger(Data, Offset); |
329 | 87 | StringRef ValueDesc = |
330 | 87 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
331 | 87 | PrintAttribute(Tag, Value, ValueDesc); |
332 | 87 | } |
333 | | |
334 | | void ARMAttributeParser::ABI_FP_user_exceptions(AttrType Tag, |
335 | | const uint8_t *Data, |
336 | 5 | uint32_t &Offset) { |
337 | 5 | static const char *const Strings[] = { "Not Permitted", "IEEE-754" }; |
338 | 5 | |
339 | 5 | uint64_t Value = ParseInteger(Data, Offset); |
340 | 5 | StringRef ValueDesc = |
341 | 5 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
342 | 5 | PrintAttribute(Tag, Value, ValueDesc); |
343 | 5 | } |
344 | | |
345 | | void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data, |
346 | 91 | uint32_t &Offset) { |
347 | 91 | static const char *const Strings[] = { |
348 | 91 | "Not Permitted", "Finite Only", "RTABI", "IEEE-754" |
349 | 91 | }; |
350 | 91 | |
351 | 91 | uint64_t Value = ParseInteger(Data, Offset); |
352 | 91 | StringRef ValueDesc = |
353 | 91 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
354 | 91 | PrintAttribute(Tag, Value, ValueDesc); |
355 | 91 | } |
356 | | |
357 | | void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data, |
358 | 100 | uint32_t &Offset) { |
359 | 100 | static const char *const Strings[] = { |
360 | 100 | "Not Permitted", "8-byte alignment", "4-byte alignment", "Reserved" |
361 | 100 | }; |
362 | 100 | |
363 | 100 | uint64_t Value = ParseInteger(Data, Offset); |
364 | 100 | |
365 | 100 | std::string Description; |
366 | 100 | if (Value < array_lengthof(Strings)) |
367 | 91 | Description = std::string(Strings[Value]); |
368 | 9 | else if (Value <= 12) |
369 | 9 | Description = std::string("8-byte alignment, ") + utostr(1ULL << Value) |
370 | 9 | + std::string("-byte extended alignment"); |
371 | 0 | else |
372 | 0 | Description = "Invalid"; |
373 | 100 | |
374 | 100 | PrintAttribute(Tag, Value, Description); |
375 | 100 | } |
376 | | |
377 | | void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data, |
378 | 100 | uint32_t &Offset) { |
379 | 100 | static const char *const Strings[] = { |
380 | 100 | "Not Required", "8-byte data alignment", "8-byte data and code alignment", |
381 | 100 | "Reserved" |
382 | 100 | }; |
383 | 100 | |
384 | 100 | uint64_t Value = ParseInteger(Data, Offset); |
385 | 100 | |
386 | 100 | std::string Description; |
387 | 100 | if (Value < array_lengthof(Strings)) |
388 | 91 | Description = std::string(Strings[Value]); |
389 | 9 | else if (Value <= 12) |
390 | 9 | Description = std::string("8-byte stack alignment, ") + |
391 | 9 | utostr(1ULL << Value) + std::string("-byte data alignment"); |
392 | 0 | else |
393 | 0 | Description = "Invalid"; |
394 | 100 | |
395 | 100 | PrintAttribute(Tag, Value, Description); |
396 | 100 | } |
397 | | |
398 | | void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data, |
399 | 53 | uint32_t &Offset) { |
400 | 53 | static const char *const Strings[] = { |
401 | 53 | "Not Permitted", "Packed", "Int32", "External Int32" |
402 | 53 | }; |
403 | 53 | |
404 | 53 | uint64_t Value = ParseInteger(Data, Offset); |
405 | 53 | StringRef ValueDesc = |
406 | 53 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
407 | 53 | PrintAttribute(Tag, Value, ValueDesc); |
408 | 53 | } |
409 | | |
410 | | void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data, |
411 | 8 | uint32_t &Offset) { |
412 | 8 | static const char *const Strings[] = { |
413 | 8 | "Tag_FP_arch", "Single-Precision", "Reserved", "Tag_FP_arch (deprecated)" |
414 | 8 | }; |
415 | 8 | |
416 | 8 | uint64_t Value = ParseInteger(Data, Offset); |
417 | 8 | StringRef ValueDesc = |
418 | 8 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
419 | 8 | PrintAttribute(Tag, Value, ValueDesc); |
420 | 8 | } |
421 | | |
422 | | void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data, |
423 | 39 | uint32_t &Offset) { |
424 | 39 | static const char *const Strings[] = { |
425 | 39 | "AAPCS", "AAPCS VFP", "Custom", "Not Permitted" |
426 | 39 | }; |
427 | 39 | |
428 | 39 | uint64_t Value = ParseInteger(Data, Offset); |
429 | 39 | StringRef ValueDesc = |
430 | 39 | (Value < array_lengthof(Strings)) ? Strings[Value]38 : nullptr1 ; |
431 | 39 | PrintAttribute(Tag, Value, ValueDesc); |
432 | 39 | } |
433 | | |
434 | | void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data, |
435 | 7 | uint32_t &Offset) { |
436 | 7 | static const char *const Strings[] = { "AAPCS", "iWMMX", "Custom" }; |
437 | 7 | |
438 | 7 | uint64_t Value = ParseInteger(Data, Offset); |
439 | 7 | StringRef ValueDesc = |
440 | 7 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
441 | 7 | PrintAttribute(Tag, Value, ValueDesc); |
442 | 7 | } |
443 | | |
444 | | void ARMAttributeParser::ABI_optimization_goals(AttrType Tag, |
445 | | const uint8_t *Data, |
446 | 68 | uint32_t &Offset) { |
447 | 68 | static const char *const Strings[] = { |
448 | 68 | "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging", |
449 | 68 | "Best Debugging" |
450 | 68 | }; |
451 | 68 | |
452 | 68 | uint64_t Value = ParseInteger(Data, Offset); |
453 | 68 | StringRef ValueDesc = |
454 | 68 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
455 | 68 | PrintAttribute(Tag, Value, ValueDesc); |
456 | 68 | } |
457 | | |
458 | | void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag, |
459 | | const uint8_t *Data, |
460 | 8 | uint32_t &Offset) { |
461 | 8 | static const char *const Strings[] = { |
462 | 8 | "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Accuracy", |
463 | 8 | "Best Accuracy" |
464 | 8 | }; |
465 | 8 | |
466 | 8 | uint64_t Value = ParseInteger(Data, Offset); |
467 | 8 | StringRef ValueDesc = |
468 | 8 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
469 | 8 | PrintAttribute(Tag, Value, ValueDesc); |
470 | 8 | } |
471 | | |
472 | | void ARMAttributeParser::compatibility(AttrType Tag, const uint8_t *Data, |
473 | 7 | uint32_t &Offset) { |
474 | 7 | uint64_t Integer = ParseInteger(Data, Offset); |
475 | 7 | StringRef String = ParseString(Data, Offset); |
476 | 7 | |
477 | 7 | if (SW) { |
478 | 7 | DictScope AS(*SW, "Attribute"); |
479 | 7 | SW->printNumber("Tag", Tag); |
480 | 7 | SW->startLine() << "Value: " << Integer << ", " << String << '\n'; |
481 | 7 | SW->printString("TagName", AttrTypeAsString(Tag, /*TagPrefix*/false)); |
482 | 7 | switch (Integer) { |
483 | 7 | case 0: |
484 | 1 | SW->printString("Description", StringRef("No Specific Requirements")); |
485 | 1 | break; |
486 | 7 | case 1: |
487 | 3 | SW->printString("Description", StringRef("AEABI Conformant")); |
488 | 3 | break; |
489 | 7 | default: |
490 | 3 | SW->printString("Description", StringRef("AEABI Non-Conformant")); |
491 | 3 | break; |
492 | 7 | } |
493 | 7 | } |
494 | 7 | } |
495 | | |
496 | | void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data, |
497 | 256 | uint32_t &Offset) { |
498 | 256 | static const char *const Strings[] = { "Not Permitted", "v6-style" }; |
499 | 256 | |
500 | 256 | uint64_t Value = ParseInteger(Data, Offset); |
501 | 256 | StringRef ValueDesc = |
502 | 256 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
503 | 256 | PrintAttribute(Tag, Value, ValueDesc); |
504 | 256 | } |
505 | | |
506 | | void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data, |
507 | 24 | uint32_t &Offset) { |
508 | 24 | static const char *const Strings[] = { "If Available", "Permitted" }; |
509 | 24 | |
510 | 24 | uint64_t Value = ParseInteger(Data, Offset); |
511 | 24 | StringRef ValueDesc = |
512 | 24 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
513 | 24 | PrintAttribute(Tag, Value, ValueDesc); |
514 | 24 | } |
515 | | |
516 | | void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data, |
517 | 54 | uint32_t &Offset) { |
518 | 54 | static const char *const Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" }; |
519 | 54 | |
520 | 54 | uint64_t Value = ParseInteger(Data, Offset); |
521 | 54 | StringRef ValueDesc = |
522 | 54 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
523 | 54 | PrintAttribute(Tag, Value, ValueDesc); |
524 | 54 | } |
525 | | |
526 | | void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data, |
527 | 25 | uint32_t &Offset) { |
528 | 25 | static const char *const Strings[] = { "Not Permitted", "Permitted" }; |
529 | 25 | |
530 | 25 | uint64_t Value = ParseInteger(Data, Offset); |
531 | 25 | StringRef ValueDesc = |
532 | 25 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
533 | 25 | PrintAttribute(Tag, Value, ValueDesc); |
534 | 25 | } |
535 | | |
536 | | void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data, |
537 | 27 | uint32_t &Offset) { |
538 | 27 | static const char *const Strings[] = { |
539 | 27 | "If Available", "Not Permitted", "Permitted" |
540 | 27 | }; |
541 | 27 | |
542 | 27 | uint64_t Value = ParseInteger(Data, Offset); |
543 | 27 | StringRef ValueDesc = |
544 | 27 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
545 | 27 | PrintAttribute(Tag, Value, ValueDesc); |
546 | 27 | } |
547 | | |
548 | | void ARMAttributeParser::DSP_extension(AttrType Tag, const uint8_t *Data, |
549 | 3 | uint32_t &Offset) { |
550 | 3 | static const char *const Strings[] = { "Not Permitted", "Permitted" }; |
551 | 3 | |
552 | 3 | uint64_t Value = ParseInteger(Data, Offset); |
553 | 3 | StringRef ValueDesc = |
554 | 3 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
555 | 3 | PrintAttribute(Tag, Value, ValueDesc); |
556 | 3 | } |
557 | | |
558 | | void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data, |
559 | 3 | uint32_t &Offset) { |
560 | 3 | static const char *const Strings[] = { "Not Permitted", "Permitted" }; |
561 | 3 | |
562 | 3 | uint64_t Value = ParseInteger(Data, Offset); |
563 | 3 | StringRef ValueDesc = |
564 | 3 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
565 | 3 | PrintAttribute(Tag, Value, ValueDesc); |
566 | 3 | } |
567 | | |
568 | | void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data, |
569 | 44 | uint32_t &Offset) { |
570 | 44 | static const char *const Strings[] = { |
571 | 44 | "Not Permitted", "TrustZone", "Virtualization Extensions", |
572 | 44 | "TrustZone + Virtualization Extensions" |
573 | 44 | }; |
574 | 44 | |
575 | 44 | uint64_t Value = ParseInteger(Data, Offset); |
576 | 44 | StringRef ValueDesc = |
577 | 44 | (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr0 ; |
578 | 44 | PrintAttribute(Tag, Value, ValueDesc); |
579 | 44 | } |
580 | | |
581 | | void ARMAttributeParser::nodefaults(AttrType Tag, const uint8_t *Data, |
582 | 1 | uint32_t &Offset) { |
583 | 1 | uint64_t Value = ParseInteger(Data, Offset); |
584 | 1 | PrintAttribute(Tag, Value, "Unspecified Tags UNDEFINED"); |
585 | 1 | } |
586 | | |
587 | | void ARMAttributeParser::ParseIndexList(const uint8_t *Data, uint32_t &Offset, |
588 | 0 | SmallVectorImpl<uint8_t> &IndexList) { |
589 | 0 | for (;;) { |
590 | 0 | unsigned Length; |
591 | 0 | uint64_t Value = decodeULEB128(Data + Offset, &Length); |
592 | 0 | Offset = Offset + Length; |
593 | 0 | if (Value == 0) |
594 | 0 | break; |
595 | 0 | IndexList.push_back(Value); |
596 | 0 | } |
597 | 0 | } |
598 | | |
599 | | void ARMAttributeParser::ParseAttributeList(const uint8_t *Data, |
600 | 467 | uint32_t &Offset, uint32_t Length) { |
601 | 3.57k | while (Offset < Length) { |
602 | 3.11k | unsigned Length; |
603 | 3.11k | uint64_t Tag = decodeULEB128(Data + Offset, &Length); |
604 | 3.11k | Offset += Length; |
605 | 3.11k | |
606 | 3.11k | bool Handled = false; |
607 | 3.11k | for (unsigned AHI = 0, AHE = array_lengthof(DisplayRoutines); |
608 | 43.0k | AHI != AHE && !Handled42.9k ; ++AHI39.9k ) { |
609 | 42.9k | if (uint64_t(DisplayRoutines[AHI].Attribute) == Tag) { |
610 | 3.06k | (this->*DisplayRoutines[AHI].Routine)(ARMBuildAttrs::AttrType(Tag), |
611 | 3.06k | Data, Offset); |
612 | 3.06k | Handled = true; |
613 | 3.06k | break; |
614 | 3.06k | } |
615 | 42.9k | } |
616 | 3.11k | if (!Handled) { |
617 | 51 | if (Tag < 32) { |
618 | 0 | errs() << "unhandled AEABI Tag " << Tag |
619 | 0 | << " (" << ARMBuildAttrs::AttrTypeAsString(Tag) << ")\n"; |
620 | 0 | continue; |
621 | 0 | } |
622 | 51 | |
623 | 51 | if (Tag % 2 == 0) |
624 | 0 | IntegerAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset); |
625 | 51 | else |
626 | 51 | StringAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset); |
627 | 51 | } |
628 | 3.11k | } |
629 | 467 | } |
630 | | |
631 | 467 | void ARMAttributeParser::ParseSubsection(const uint8_t *Data, uint32_t Length) { |
632 | 467 | uint32_t Offset = sizeof(uint32_t); /* SectionLength */ |
633 | 467 | |
634 | 467 | const char *VendorName = reinterpret_cast<const char*>(Data + Offset); |
635 | 467 | size_t VendorNameLength = std::strlen(VendorName); |
636 | 467 | Offset = Offset + VendorNameLength + 1; |
637 | 467 | |
638 | 467 | if (SW) { |
639 | 74 | SW->printNumber("SectionLength", Length); |
640 | 74 | SW->printString("Vendor", StringRef(VendorName, VendorNameLength)); |
641 | 74 | } |
642 | 467 | |
643 | 467 | if (StringRef(VendorName, VendorNameLength).lower() != "aeabi") { |
644 | 0 | return; |
645 | 0 | } |
646 | 467 | |
647 | 934 | while (467 Offset < Length) { |
648 | 467 | /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size |
649 | 467 | uint8_t Tag = Data[Offset]; |
650 | 467 | Offset = Offset + sizeof(Tag); |
651 | 467 | |
652 | 467 | uint32_t Size = |
653 | 467 | *reinterpret_cast<const support::ulittle32_t*>(Data + Offset); |
654 | 467 | Offset = Offset + sizeof(Size); |
655 | 467 | |
656 | 467 | if (SW) { |
657 | 74 | SW->printEnum("Tag", Tag, makeArrayRef(TagNames)); |
658 | 74 | SW->printNumber("Size", Size); |
659 | 74 | } |
660 | 467 | |
661 | 467 | if (Size > Length) { |
662 | 0 | errs() << "subsection length greater than section length\n"; |
663 | 0 | return; |
664 | 0 | } |
665 | 467 | |
666 | 467 | StringRef ScopeName, IndexName; |
667 | 467 | SmallVector<uint8_t, 8> Indicies; |
668 | 467 | switch (Tag) { |
669 | 467 | case ARMBuildAttrs::File: |
670 | 467 | ScopeName = "FileAttributes"; |
671 | 467 | break; |
672 | 467 | case ARMBuildAttrs::Section: |
673 | 0 | ScopeName = "SectionAttributes"; |
674 | 0 | IndexName = "Sections"; |
675 | 0 | ParseIndexList(Data, Offset, Indicies); |
676 | 0 | break; |
677 | 467 | case ARMBuildAttrs::Symbol: |
678 | 0 | ScopeName = "SymbolAttributes"; |
679 | 0 | IndexName = "Symbols"; |
680 | 0 | ParseIndexList(Data, Offset, Indicies); |
681 | 0 | break; |
682 | 467 | default: |
683 | 0 | errs() << "unrecognised tag: 0x" << Twine::utohexstr(Tag) << '\n'; |
684 | 0 | return; |
685 | 467 | } |
686 | 467 | |
687 | 467 | if (SW) { |
688 | 74 | DictScope ASS(*SW, ScopeName); |
689 | 74 | if (!Indicies.empty()) |
690 | 0 | SW->printList(IndexName, Indicies); |
691 | 74 | ParseAttributeList(Data, Offset, Length); |
692 | 393 | } else { |
693 | 393 | ParseAttributeList(Data, Offset, Length); |
694 | 393 | } |
695 | 467 | } |
696 | 467 | } |
697 | | |
698 | 469 | void ARMAttributeParser::Parse(ArrayRef<uint8_t> Section, bool isLittle) { |
699 | 469 | uint64_t Offset = 1; |
700 | 469 | unsigned SectionNumber = 0; |
701 | 469 | |
702 | 936 | while (Offset < Section.size()) { |
703 | 469 | uint32_t SectionLength = isLittle ? |
704 | 469 | support::endian::read32le(Section.data() + Offset) : |
705 | 469 | support::endian::read32be(Section.data() + Offset)0 ; |
706 | 469 | |
707 | 469 | if (SW) { |
708 | 74 | SW->startLine() << "Section " << ++SectionNumber << " {\n"; |
709 | 74 | SW->indent(); |
710 | 74 | } |
711 | 469 | |
712 | 469 | if (SectionLength == 0 || (SectionLength + Offset) > Section.size()468 ) { |
713 | 2 | errs() << "invalid subsection length " << SectionLength << " at offset " |
714 | 2 | << Offset << "\n"; |
715 | 2 | return; |
716 | 2 | } |
717 | 467 | |
718 | 467 | ParseSubsection(Section.data() + Offset, SectionLength); |
719 | 467 | Offset = Offset + SectionLength; |
720 | 467 | |
721 | 467 | if (SW) { |
722 | 74 | SW->unindent(); |
723 | 74 | SW->startLine() << "}\n"; |
724 | 74 | } |
725 | 467 | } |
726 | 469 | } |
727 | | } |