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