Coverage Report

Created: 2019-07-24 05:18

/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
}