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