1 //===--- ARMAttributeParser.cpp - ARM Attribute Information Printer -------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "ARMAttributeParser.h" 11 #include "llvm/ADT/STLExtras.h" 12 #include "llvm/ADT/StringExtras.h" 13 #include "llvm/Support/LEB128.h" 14 #include "llvm/Support/ScopedPrinter.h" 15 16 using namespace llvm; 17 using namespace llvm::ARMBuildAttrs; 18 19 20 static const EnumEntry<unsigned> TagNames[] = { 21 { "Tag_File", ARMBuildAttrs::File }, 22 { "Tag_Section", ARMBuildAttrs::Section }, 23 { "Tag_Symbol", ARMBuildAttrs::Symbol }, 24 }; 25 26 namespace llvm { 27 #define ATTRIBUTE_HANDLER(Attr_) \ 28 { ARMBuildAttrs::Attr_, &ARMAttributeParser::Attr_ } 29 30 const ARMAttributeParser::DisplayHandler 31 ARMAttributeParser::DisplayRoutines[] = { 32 { ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::StringAttribute, }, 33 { ARMBuildAttrs::CPU_name, &ARMAttributeParser::StringAttribute }, 34 ATTRIBUTE_HANDLER(CPU_arch), 35 ATTRIBUTE_HANDLER(CPU_arch_profile), 36 ATTRIBUTE_HANDLER(ARM_ISA_use), 37 ATTRIBUTE_HANDLER(THUMB_ISA_use), 38 ATTRIBUTE_HANDLER(FP_arch), 39 ATTRIBUTE_HANDLER(WMMX_arch), 40 ATTRIBUTE_HANDLER(Advanced_SIMD_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 Length; 77 uint64_t Value = decodeULEB128(Data + Offset, &Length); 78 Offset = Offset + Length; 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 SW.printNumber(ARMBuildAttrs::AttrTypeAsString(Tag), 93 ParseInteger(Data, Offset)); 94 } 95 96 void ARMAttributeParser::StringAttribute(AttrType Tag, const uint8_t *Data, 97 uint32_t &Offset) { 98 StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false); 99 100 DictScope AS(SW, "Attribute"); 101 SW.printNumber("Tag", Tag); 102 if (!TagName.empty()) 103 SW.printString("TagName", TagName); 104 SW.printString("Value", ParseString(Data, Offset)); 105 } 106 107 void ARMAttributeParser::PrintAttribute(unsigned Tag, unsigned Value, 108 StringRef ValueDesc) { 109 StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false); 110 111 DictScope AS(SW, "Attribute"); 112 SW.printNumber("Tag", Tag); 113 SW.printNumber("Value", Value); 114 if (!TagName.empty()) 115 SW.printString("TagName", TagName); 116 if (!ValueDesc.empty()) 117 SW.printString("Description", ValueDesc); 118 } 119 120 void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data, 121 uint32_t &Offset) { 122 static const char *const Strings[] = { 123 "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6", 124 "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M", 125 "ARM v7E-M", "ARM v8" 126 }; 127 128 uint64_t Value = ParseInteger(Data, Offset); 129 StringRef ValueDesc = 130 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 131 PrintAttribute(Tag, Value, ValueDesc); 132 } 133 134 void ARMAttributeParser::CPU_arch_profile(AttrType Tag, const uint8_t *Data, 135 uint32_t &Offset) { 136 uint64_t Encoded = ParseInteger(Data, Offset); 137 138 StringRef Profile; 139 switch (Encoded) { 140 default: Profile = "Unknown"; break; 141 case 'A': Profile = "Application"; break; 142 case 'R': Profile = "Real-time"; break; 143 case 'M': Profile = "Microcontroller"; break; 144 case 'S': Profile = "Classic"; break; 145 case 0: Profile = "None"; break; 146 } 147 148 PrintAttribute(Tag, Encoded, Profile); 149 } 150 151 void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data, 152 uint32_t &Offset) { 153 static const char *const Strings[] = { "Not Permitted", "Permitted" }; 154 155 uint64_t Value = ParseInteger(Data, Offset); 156 StringRef ValueDesc = 157 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 158 PrintAttribute(Tag, Value, ValueDesc); 159 } 160 161 void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data, 162 uint32_t &Offset) { 163 static const char *const Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" }; 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::FP_arch(AttrType Tag, const uint8_t *Data, 172 uint32_t &Offset) { 173 static const char *const Strings[] = { 174 "Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4", 175 "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16" 176 }; 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::WMMX_arch(AttrType Tag, const uint8_t *Data, 185 uint32_t &Offset) { 186 static const char *const Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" }; 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::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data, 195 uint32_t &Offset) { 196 static const char *const Strings[] = { 197 "Not Permitted", "NEONv1", "NEONv2+FMA", "ARMv8-a NEON", "ARMv8.1-a NEON" 198 }; 199 200 uint64_t Value = ParseInteger(Data, Offset); 201 StringRef ValueDesc = 202 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 203 PrintAttribute(Tag, Value, ValueDesc); 204 } 205 206 void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data, 207 uint32_t &Offset) { 208 static const char *const Strings[] = { 209 "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004", 210 "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)" 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::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data, 220 uint32_t &Offset) { 221 static const char *const Strings[] = { "v6", "Static Base", "TLS", "Unused" }; 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_RW_data(AttrType Tag, const uint8_t *Data, 230 uint32_t &Offset) { 231 static const char *const Strings[] = { 232 "Absolute", "PC-relative", "SB-relative", "Not Permitted" 233 }; 234 235 uint64_t Value = ParseInteger(Data, Offset); 236 StringRef ValueDesc = 237 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 238 PrintAttribute(Tag, Value, ValueDesc); 239 } 240 241 void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data, 242 uint32_t &Offset) { 243 static const char *const Strings[] = { 244 "Absolute", "PC-relative", "Not Permitted" 245 }; 246 247 uint64_t Value = ParseInteger(Data, Offset); 248 StringRef ValueDesc = 249 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 250 PrintAttribute(Tag, Value, ValueDesc); 251 } 252 253 void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data, 254 uint32_t &Offset) { 255 static const char *const Strings[] = { 256 "Not Permitted", "Direct", "GOT-Indirect" 257 }; 258 259 uint64_t Value = ParseInteger(Data, Offset); 260 StringRef ValueDesc = 261 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 262 PrintAttribute(Tag, Value, ValueDesc); 263 } 264 265 void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data, 266 uint32_t &Offset) { 267 static const char *const Strings[] = { 268 "Not Permitted", "Unknown", "2-byte", "Unknown", "4-byte" 269 }; 270 271 uint64_t Value = ParseInteger(Data, Offset); 272 StringRef ValueDesc = 273 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 274 PrintAttribute(Tag, Value, ValueDesc); 275 } 276 277 void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data, 278 uint32_t &Offset) { 279 static const char *const Strings[] = { "IEEE-754", "Runtime" }; 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_denormal(AttrType Tag, const uint8_t *Data, 288 uint32_t &Offset) { 289 static const char *const Strings[] = { 290 "Unsupported", "IEEE-754", "Sign Only" 291 }; 292 293 uint64_t Value = ParseInteger(Data, Offset); 294 StringRef ValueDesc = 295 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 296 PrintAttribute(Tag, Value, ValueDesc); 297 } 298 299 void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data, 300 uint32_t &Offset) { 301 static const char *const Strings[] = { "Not Permitted", "IEEE-754" }; 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_user_exceptions(AttrType Tag, 310 const uint8_t *Data, 311 uint32_t &Offset) { 312 static const char *const Strings[] = { "Not Permitted", "IEEE-754" }; 313 314 uint64_t Value = ParseInteger(Data, Offset); 315 StringRef ValueDesc = 316 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 317 PrintAttribute(Tag, Value, ValueDesc); 318 } 319 320 void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data, 321 uint32_t &Offset) { 322 static const char *const Strings[] = { 323 "Not Permitted", "Finite Only", "RTABI", "IEEE-754" 324 }; 325 326 uint64_t Value = ParseInteger(Data, Offset); 327 StringRef ValueDesc = 328 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 329 PrintAttribute(Tag, Value, ValueDesc); 330 } 331 332 void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data, 333 uint32_t &Offset) { 334 static const char *const Strings[] = { 335 "Not Permitted", "8-byte alignment", "4-byte alignment", "Reserved" 336 }; 337 338 uint64_t Value = ParseInteger(Data, Offset); 339 340 std::string Description; 341 if (Value < array_lengthof(Strings)) 342 Description = std::string(Strings[Value]); 343 else if (Value <= 12) 344 Description = std::string("8-byte alignment, ") + utostr(1ULL << Value) 345 + std::string("-byte extended alignment"); 346 else 347 Description = "Invalid"; 348 349 PrintAttribute(Tag, Value, Description); 350 } 351 352 void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data, 353 uint32_t &Offset) { 354 static const char *const Strings[] = { 355 "Not Required", "8-byte data alignment", "8-byte data and code alignment", 356 "Reserved" 357 }; 358 359 uint64_t Value = ParseInteger(Data, Offset); 360 361 std::string Description; 362 if (Value < array_lengthof(Strings)) 363 Description = std::string(Strings[Value]); 364 else if (Value <= 12) 365 Description = std::string("8-byte stack alignment, ") + 366 utostr(1ULL << Value) + std::string("-byte data alignment"); 367 else 368 Description = "Invalid"; 369 370 PrintAttribute(Tag, Value, Description); 371 } 372 373 void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data, 374 uint32_t &Offset) { 375 static const char *const Strings[] = { 376 "Not Permitted", "Packed", "Int32", "External Int32" 377 }; 378 379 uint64_t Value = ParseInteger(Data, Offset); 380 StringRef ValueDesc = 381 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 382 PrintAttribute(Tag, Value, ValueDesc); 383 } 384 385 void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data, 386 uint32_t &Offset) { 387 static const char *const Strings[] = { 388 "Tag_FP_arch", "Single-Precision", "Reserved", "Tag_FP_arch (deprecated)" 389 }; 390 391 uint64_t Value = ParseInteger(Data, Offset); 392 StringRef ValueDesc = 393 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 394 PrintAttribute(Tag, Value, ValueDesc); 395 } 396 397 void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data, 398 uint32_t &Offset) { 399 static const char *const Strings[] = { 400 "AAPCS", "AAPCS VFP", "Custom", "Not Permitted" 401 }; 402 403 uint64_t Value = ParseInteger(Data, Offset); 404 StringRef ValueDesc = 405 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 406 PrintAttribute(Tag, Value, ValueDesc); 407 } 408 409 void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data, 410 uint32_t &Offset) { 411 static const char *const Strings[] = { "AAPCS", "iWMMX", "Custom" }; 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_optimization_goals(AttrType Tag, 420 const uint8_t *Data, 421 uint32_t &Offset) { 422 static const char *const Strings[] = { 423 "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging", 424 "Best Debugging" 425 }; 426 427 uint64_t Value = ParseInteger(Data, Offset); 428 StringRef ValueDesc = 429 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 430 PrintAttribute(Tag, Value, ValueDesc); 431 } 432 433 void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag, 434 const uint8_t *Data, 435 uint32_t &Offset) { 436 static const char *const Strings[] = { 437 "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Accuracy", 438 "Best Accuracy" 439 }; 440 441 uint64_t Value = ParseInteger(Data, Offset); 442 StringRef ValueDesc = 443 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 444 PrintAttribute(Tag, Value, ValueDesc); 445 } 446 447 void ARMAttributeParser::compatibility(AttrType Tag, const uint8_t *Data, 448 uint32_t &Offset) { 449 uint64_t Integer = ParseInteger(Data, Offset); 450 StringRef String = ParseString(Data, Offset); 451 452 DictScope AS(SW, "Attribute"); 453 SW.printNumber("Tag", Tag); 454 SW.startLine() << "Value: " << Integer << ", " << String << '\n'; 455 SW.printString("TagName", AttrTypeAsString(Tag, /*TagPrefix*/false)); 456 switch (Integer) { 457 case 0: 458 SW.printString("Description", StringRef("No Specific Requirements")); 459 break; 460 case 1: 461 SW.printString("Description", StringRef("AEABI Conformant")); 462 break; 463 default: 464 SW.printString("Description", StringRef("AEABI Non-Conformant")); 465 break; 466 } 467 } 468 469 void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data, 470 uint32_t &Offset) { 471 static const char *const Strings[] = { "Not Permitted", "v6-style" }; 472 473 uint64_t Value = ParseInteger(Data, Offset); 474 StringRef ValueDesc = 475 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 476 PrintAttribute(Tag, Value, ValueDesc); 477 } 478 479 void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data, 480 uint32_t &Offset) { 481 static const char *const Strings[] = { "If Available", "Permitted" }; 482 483 uint64_t Value = ParseInteger(Data, Offset); 484 StringRef ValueDesc = 485 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 486 PrintAttribute(Tag, Value, ValueDesc); 487 } 488 489 void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data, 490 uint32_t &Offset) { 491 static const char *const Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" }; 492 493 uint64_t Value = ParseInteger(Data, Offset); 494 StringRef ValueDesc = 495 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 496 PrintAttribute(Tag, Value, ValueDesc); 497 } 498 499 void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data, 500 uint32_t &Offset) { 501 static const char *const Strings[] = { "Not Permitted", "Permitted" }; 502 503 uint64_t Value = ParseInteger(Data, Offset); 504 StringRef ValueDesc = 505 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 506 PrintAttribute(Tag, Value, ValueDesc); 507 } 508 509 void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data, 510 uint32_t &Offset) { 511 static const char *const Strings[] = { 512 "If Available", "Not Permitted", "Permitted" 513 }; 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::DSP_extension(AttrType Tag, const uint8_t *Data, 522 uint32_t &Offset) { 523 static const char *const Strings[] = { "Not Permitted", "Permitted" }; 524 525 uint64_t Value = ParseInteger(Data, Offset); 526 StringRef ValueDesc = 527 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 528 PrintAttribute(Tag, Value, ValueDesc); 529 } 530 531 void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data, 532 uint32_t &Offset) { 533 static const char *const Strings[] = { "Not Permitted", "Permitted" }; 534 535 uint64_t Value = ParseInteger(Data, Offset); 536 StringRef ValueDesc = 537 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 538 PrintAttribute(Tag, Value, ValueDesc); 539 } 540 541 void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data, 542 uint32_t &Offset) { 543 static const char *const Strings[] = { 544 "Not Permitted", "TrustZone", "Virtualization Extensions", 545 "TrustZone + Virtualization Extensions" 546 }; 547 548 uint64_t Value = ParseInteger(Data, Offset); 549 StringRef ValueDesc = 550 (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; 551 PrintAttribute(Tag, Value, ValueDesc); 552 } 553 554 void ARMAttributeParser::nodefaults(AttrType Tag, const uint8_t *Data, 555 uint32_t &Offset) { 556 uint64_t Value = ParseInteger(Data, Offset); 557 PrintAttribute(Tag, Value, "Unspecified Tags UNDEFINED"); 558 } 559 560 void ARMAttributeParser::ParseIndexList(const uint8_t *Data, uint32_t &Offset, 561 SmallVectorImpl<uint8_t> &IndexList) { 562 for (;;) { 563 unsigned Length; 564 uint64_t Value = decodeULEB128(Data + Offset, &Length); 565 Offset = Offset + Length; 566 if (Value == 0) 567 break; 568 IndexList.push_back(Value); 569 } 570 } 571 572 void ARMAttributeParser::ParseAttributeList(const uint8_t *Data, 573 uint32_t &Offset, uint32_t Length) { 574 while (Offset < Length) { 575 unsigned Length; 576 uint64_t Tag = decodeULEB128(Data + Offset, &Length); 577 Offset += Length; 578 579 bool Handled = false; 580 for (unsigned AHI = 0, AHE = array_lengthof(DisplayRoutines); 581 AHI != AHE && !Handled; ++AHI) { 582 if (DisplayRoutines[AHI].Attribute == Tag) { 583 (this->*DisplayRoutines[AHI].Routine)(ARMBuildAttrs::AttrType(Tag), 584 Data, Offset); 585 Handled = true; 586 break; 587 } 588 } 589 if (!Handled) { 590 if (Tag < 32) { 591 errs() << "unhandled AEABI Tag " << Tag 592 << " (" << ARMBuildAttrs::AttrTypeAsString(Tag) << ")\n"; 593 continue; 594 } 595 596 if (Tag % 2 == 0) 597 IntegerAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset); 598 else 599 StringAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset); 600 } 601 } 602 } 603 604 void ARMAttributeParser::ParseSubsection(const uint8_t *Data, uint32_t Length) { 605 uint32_t Offset = sizeof(uint32_t); /* SectionLength */ 606 607 SW.printNumber("SectionLength", Length); 608 609 const char *VendorName = reinterpret_cast<const char*>(Data + Offset); 610 size_t VendorNameLength = std::strlen(VendorName); 611 SW.printString("Vendor", StringRef(VendorName, VendorNameLength)); 612 Offset = Offset + VendorNameLength + 1; 613 614 if (StringRef(VendorName, VendorNameLength).lower() != "aeabi") 615 return; 616 617 while (Offset < Length) { 618 /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size 619 uint8_t Tag = Data[Offset]; 620 SW.printEnum("Tag", Tag, makeArrayRef(TagNames)); 621 Offset = Offset + sizeof(Tag); 622 623 uint32_t Size = 624 *reinterpret_cast<const support::ulittle32_t*>(Data + Offset); 625 SW.printNumber("Size", Size); 626 Offset = Offset + sizeof(Size); 627 628 if (Size > Length) { 629 errs() << "subsection length greater than section length\n"; 630 return; 631 } 632 633 StringRef ScopeName, IndexName; 634 SmallVector<uint8_t, 8> Indicies; 635 switch (Tag) { 636 case ARMBuildAttrs::File: 637 ScopeName = "FileAttributes"; 638 break; 639 case ARMBuildAttrs::Section: 640 ScopeName = "SectionAttributes"; 641 IndexName = "Sections"; 642 ParseIndexList(Data, Offset, Indicies); 643 break; 644 case ARMBuildAttrs::Symbol: 645 ScopeName = "SymbolAttributes"; 646 IndexName = "Symbols"; 647 ParseIndexList(Data, Offset, Indicies); 648 break; 649 default: 650 errs() << "unrecognised tag: 0x" << utohexstr(Tag) << '\n'; 651 return; 652 } 653 654 DictScope ASS(SW, ScopeName); 655 656 if (!Indicies.empty()) 657 SW.printList(IndexName, Indicies); 658 659 ParseAttributeList(Data, Offset, Length); 660 } 661 } 662 663 void ARMAttributeParser::Parse(ArrayRef<uint8_t> Section) { 664 size_t Offset = 1; 665 unsigned SectionNumber = 0; 666 667 while (Offset < Section.size()) { 668 uint32_t SectionLength = 669 *reinterpret_cast<const support::ulittle32_t*>(Section.data() + Offset); 670 671 SW.startLine() << "Section " << ++SectionNumber << " {\n"; 672 SW.indent(); 673 674 ParseSubsection(Section.data() + Offset, SectionLength); 675 Offset = Offset + SectionLength; 676 677 SW.unindent(); 678 SW.startLine() << "}\n"; 679 } 680 } 681 } 682 683