1 //===--- ARMEHABIPrinter.h - ARM EHABI Unwind 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 #ifndef LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H 11 #define LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H 12 13 #include "Error.h" 14 #include "StreamWriter.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/Object/ELF.h" 17 #include "llvm/Object/ELFTypes.h" 18 #include "llvm/Support/ARMEHABI.h" 19 #include "llvm/Support/Debug.h" 20 #include "llvm/Support/Endian.h" 21 #include "llvm/Support/Format.h" 22 #include "llvm/Support/type_traits.h" 23 24 namespace llvm { 25 namespace ARM { 26 namespace EHABI { 27 28 class OpcodeDecoder { 29 StreamWriter &SW; 30 raw_ostream &OS; 31 32 struct RingEntry { 33 uint8_t Mask; 34 uint8_t Value; 35 void (OpcodeDecoder::*Routine)(const uint8_t *Opcodes, unsigned &OI); 36 }; 37 static const RingEntry Ring[]; 38 39 void Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI); 40 void Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI); 41 void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, unsigned &OI); 42 void Decode_10011101(const uint8_t *Opcodes, unsigned &OI); 43 void Decode_10011111(const uint8_t *Opcodes, unsigned &OI); 44 void Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI); 45 void Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI); 46 void Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI); 47 void Decode_10110000(const uint8_t *Opcodes, unsigned &OI); 48 void Decode_10110001_0000iiii(const uint8_t *Opcodes, unsigned &OI); 49 void Decode_10110010_uleb128(const uint8_t *Opcodes, unsigned &OI); 50 void Decode_10110011_sssscccc(const uint8_t *Opcodes, unsigned &OI); 51 void Decode_101101nn(const uint8_t *Opcodes, unsigned &OI); 52 void Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI); 53 void Decode_11000110_sssscccc(const uint8_t *Opcodes, unsigned &OI); 54 void Decode_11000111_0000iiii(const uint8_t *Opcodes, unsigned &OI); 55 void Decode_11001000_sssscccc(const uint8_t *Opcodes, unsigned &OI); 56 void Decode_11001001_sssscccc(const uint8_t *Opcodes, unsigned &OI); 57 void Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI); 58 void Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI); 59 void Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI); 60 void Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI); 61 62 void PrintGPR(uint16_t GPRMask); 63 void PrintRegisters(uint32_t Mask, StringRef Prefix); 64 65 public: 66 OpcodeDecoder(StreamWriter &SW) : SW(SW), OS(SW.getOStream()) {} 67 void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length); 68 }; 69 70 const OpcodeDecoder::RingEntry OpcodeDecoder::Ring[] = { 71 { 0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx }, 72 { 0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx }, 73 { 0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii }, 74 { 0xff, 0x9d, &OpcodeDecoder::Decode_10011101 }, 75 { 0xff, 0x9f, &OpcodeDecoder::Decode_10011111 }, 76 { 0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn }, 77 { 0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn }, 78 { 0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn }, 79 { 0xff, 0xb0, &OpcodeDecoder::Decode_10110000 }, 80 { 0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii }, 81 { 0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128 }, 82 { 0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc }, 83 { 0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn }, 84 { 0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn }, 85 { 0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc }, 86 { 0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii }, 87 { 0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc }, 88 { 0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc }, 89 { 0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy }, 90 { 0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn }, 91 { 0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn }, 92 { 0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy }, 93 }; 94 95 void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI) { 96 uint8_t Opcode = Opcodes[OI++ ^ 3]; 97 SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode, 98 ((Opcode & 0x3f) << 2) + 4); 99 } 100 void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI) { 101 uint8_t Opcode = Opcodes[OI++ ^ 3]; 102 SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode, 103 ((Opcode & 0x3f) << 2) + 4); 104 } 105 void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, 106 unsigned &OI) { 107 uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 108 uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 109 110 uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12); 111 SW.startLine() 112 << format("0x%02X 0x%02X ; %s", 113 Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind"); 114 if (GPRMask) 115 PrintGPR(GPRMask); 116 OS << '\n'; 117 } 118 void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes, unsigned &OI) { 119 uint8_t Opcode = Opcodes[OI++ ^ 3]; 120 SW.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode); 121 } 122 void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes, unsigned &OI) { 123 uint8_t Opcode = Opcodes[OI++ ^ 3]; 124 SW.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode); 125 } 126 void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI) { 127 uint8_t Opcode = Opcodes[OI++ ^ 3]; 128 SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f)); 129 } 130 void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI) { 131 uint8_t Opcode = Opcodes[OI++ ^ 3]; 132 SW.startLine() << format("0x%02X ; pop ", Opcode); 133 PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4)); 134 OS << '\n'; 135 } 136 void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI) { 137 uint8_t Opcode = Opcodes[OI++ ^ 3]; 138 SW.startLine() << format("0x%02X ; pop ", Opcode); 139 PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14)); 140 OS << '\n'; 141 } 142 void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes, unsigned &OI) { 143 uint8_t Opcode = Opcodes[OI++ ^ 3]; 144 SW.startLine() << format("0x%02X ; finish\n", Opcode); 145 } 146 void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes, 147 unsigned &OI) { 148 uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 149 uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 150 151 SW.startLine() 152 << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1, 153 ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop "); 154 if (((Opcode1 & 0xf0) == 0x00) && Opcode1) 155 PrintGPR((Opcode1 & 0x0f)); 156 OS << '\n'; 157 } 158 void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes, 159 unsigned &OI) { 160 uint8_t Opcode = Opcodes[OI++ ^ 3]; 161 SW.startLine() << format("0x%02X ", Opcode); 162 163 SmallVector<uint8_t, 4> ULEB; 164 do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80); 165 166 for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI) 167 OS << format("0x%02X ", ULEB[BI]); 168 169 uint64_t Value = 0; 170 for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI) 171 Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI)); 172 173 OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2)); 174 } 175 void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes, 176 unsigned &OI) { 177 uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 178 uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 179 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 180 uint8_t Start = ((Opcode1 & 0xf0) >> 4); 181 uint8_t Count = ((Opcode1 & 0x0f) >> 0); 182 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d"); 183 OS << '\n'; 184 } 185 void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes, unsigned &OI) { 186 uint8_t Opcode = Opcodes[OI++ ^ 3]; 187 SW.startLine() << format("0x%02X ; spare\n", Opcode); 188 } 189 void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI) { 190 uint8_t Opcode = Opcodes[OI++ ^ 3]; 191 SW.startLine() << format("0x%02X ; pop ", Opcode); 192 PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d"); 193 OS << '\n'; 194 } 195 void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes, 196 unsigned &OI) { 197 uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 198 uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 199 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 200 uint8_t Start = ((Opcode1 & 0xf0) >> 4); 201 uint8_t Count = ((Opcode1 & 0x0f) >> 0); 202 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR"); 203 OS << '\n'; 204 } 205 void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes, 206 unsigned &OI) { 207 uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 208 uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 209 SW.startLine() 210 << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1, 211 ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop "); 212 if ((Opcode1 & 0xf0) == 0x00 && Opcode1) 213 PrintRegisters(Opcode1 & 0x0f, "wCGR"); 214 OS << '\n'; 215 } 216 void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes, 217 unsigned &OI) { 218 uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 219 uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 220 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 221 uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4); 222 uint8_t Count = ((Opcode1 & 0x0f) >> 0); 223 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d"); 224 OS << '\n'; 225 } 226 void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes, 227 unsigned &OI) { 228 uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 229 uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 230 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 231 uint8_t Start = ((Opcode1 & 0xf0) >> 4); 232 uint8_t Count = ((Opcode1 & 0x0f) >> 0); 233 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d"); 234 OS << '\n'; 235 } 236 void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI) { 237 uint8_t Opcode = Opcodes[OI++ ^ 3]; 238 SW.startLine() << format("0x%02X ; spare\n", Opcode); 239 } 240 void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI) { 241 uint8_t Opcode = Opcodes[OI++ ^ 3]; 242 SW.startLine() << format("0x%02X ; pop ", Opcode); 243 PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR"); 244 OS << '\n'; 245 } 246 void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI) { 247 uint8_t Opcode = Opcodes[OI++ ^ 3]; 248 SW.startLine() << format("0x%02X ; pop ", Opcode); 249 PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d"); 250 OS << '\n'; 251 } 252 void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI) { 253 uint8_t Opcode = Opcodes[OI++ ^ 3]; 254 SW.startLine() << format("0x%02X ; spare\n", Opcode); 255 } 256 257 void OpcodeDecoder::PrintGPR(uint16_t GPRMask) { 258 static const char *GPRRegisterNames[16] = { 259 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", 260 "fp", "ip", "sp", "lr", "pc" 261 }; 262 263 OS << '{'; 264 bool Comma = false; 265 for (unsigned RI = 0, RE = 17; RI < RE; ++RI) { 266 if (GPRMask & (1 << RI)) { 267 if (Comma) 268 OS << ", "; 269 OS << GPRRegisterNames[RI]; 270 Comma = true; 271 } 272 } 273 OS << '}'; 274 } 275 276 void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) { 277 OS << '{'; 278 bool Comma = false; 279 for (unsigned RI = 0, RE = 32; RI < RE; ++RI) { 280 if (VFPMask & (1 << RI)) { 281 if (Comma) 282 OS << ", "; 283 OS << Prefix << RI; 284 Comma = true; 285 } 286 } 287 OS << '}'; 288 } 289 290 void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset, size_t Length) { 291 for (unsigned OCI = Offset; OCI < Length + Offset; ) { 292 bool Decoded = false; 293 for (unsigned REI = 0, REE = array_lengthof(Ring); 294 REI != REE && !Decoded; ++REI) { 295 if ((Opcodes[OCI ^ 3] & Ring[REI].Mask) == Ring[REI].Value) { 296 (this->*Ring[REI].Routine)(Opcodes, OCI); 297 Decoded = true; 298 break; 299 } 300 } 301 if (!Decoded) 302 SW.startLine() << format("0x%02X ; reserved\n", Opcodes[OCI++ ^ 3]); 303 } 304 } 305 306 template <typename ET> 307 class PrinterContext { 308 typedef typename object::ELFFile<ET>::Elf_Sym Elf_Sym; 309 typedef typename object::ELFFile<ET>::Elf_Shdr Elf_Shdr; 310 typedef typename object::ELFFile<ET>::Elf_Rel Elf_Rel; 311 typedef typename object::ELFFile<ET>::Elf_Word Elf_Word; 312 313 StreamWriter &SW; 314 const object::ELFFile<ET> *ELF; 315 const Elf_Shdr *Symtab; 316 ArrayRef<Elf_Word> ShndxTable; 317 318 static const size_t IndexTableEntrySize; 319 320 static uint64_t PREL31(uint32_t Address, uint32_t Place) { 321 uint64_t Location = Address & 0x7fffffff; 322 if (Location & 0x04000000) 323 Location |= (uint64_t) ~0x7fffffff; 324 return Location + Place; 325 } 326 327 ErrorOr<StringRef> FunctionAtAddress(unsigned Section, uint64_t Address) const; 328 const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex, 329 off_t IndexTableOffset) const; 330 331 void PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *IT) const; 332 void PrintExceptionTable(const Elf_Shdr *IT, const Elf_Shdr *EHT, 333 uint64_t TableEntryOffset) const; 334 void PrintOpcodes(const uint8_t *Entry, size_t Length, off_t Offset) const; 335 336 public: 337 PrinterContext(StreamWriter &SW, const object::ELFFile<ET> *ELF, 338 const Elf_Shdr *Symtab) 339 : SW(SW), ELF(ELF), Symtab(Symtab) {} 340 341 void PrintUnwindInformation() const; 342 }; 343 344 template <typename ET> 345 const size_t PrinterContext<ET>::IndexTableEntrySize = 8; 346 347 template <typename ET> 348 ErrorOr<StringRef> 349 PrinterContext<ET>::FunctionAtAddress(unsigned Section, 350 uint64_t Address) const { 351 ErrorOr<StringRef> StrTableOrErr = ELF->getStringTableForSymtab(*Symtab); 352 error(StrTableOrErr.getError()); 353 StringRef StrTable = *StrTableOrErr; 354 355 for (const Elf_Sym &Sym : ELF->symbols(Symtab)) 356 if (Sym.st_shndx == Section && Sym.st_value == Address && 357 Sym.getType() == ELF::STT_FUNC) 358 return Sym.getName(StrTable); 359 return readobj_error::unknown_symbol; 360 } 361 362 template <typename ET> 363 const typename object::ELFFile<ET>::Elf_Shdr * 364 PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex, 365 off_t IndexTableOffset) const { 366 /// Iterate through the sections, searching for the relocation section 367 /// associated with the unwind index table section specified by 368 /// IndexSectionIndex. Iterate the associated section searching for the 369 /// relocation associated with the index table entry specified by 370 /// IndexTableOffset. The symbol is the section symbol for the exception 371 /// handling table. Use this symbol to recover the actual exception handling 372 /// table. 373 374 for (const Elf_Shdr &Sec : ELF->sections()) { 375 if (Sec.sh_type != ELF::SHT_REL || Sec.sh_info != IndexSectionIndex) 376 continue; 377 378 ErrorOr<const Elf_Shdr *> SymTabOrErr = ELF->getSection(Sec.sh_link); 379 error(SymTabOrErr.getError()); 380 const Elf_Shdr *SymTab = *SymTabOrErr; 381 382 for (const Elf_Rel &R : ELF->rels(&Sec)) { 383 if (R.r_offset != static_cast<unsigned>(IndexTableOffset)) 384 continue; 385 386 typename object::ELFFile<ET>::Elf_Rela RelA; 387 RelA.r_offset = R.r_offset; 388 RelA.r_info = R.r_info; 389 RelA.r_addend = 0; 390 391 const Elf_Sym *Symbol = ELF->getRelocationSymbol(&RelA, SymTab); 392 393 ErrorOr<const Elf_Shdr *> Ret = 394 ELF->getSection(Symbol, SymTab, ShndxTable); 395 if (std::error_code EC = Ret.getError()) 396 report_fatal_error(EC.message()); 397 return *Ret; 398 } 399 } 400 return nullptr; 401 } 402 403 template <typename ET> 404 void PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr *IT, 405 const Elf_Shdr *EHT, 406 uint64_t TableEntryOffset) const { 407 ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(EHT); 408 if (!Contents) 409 return; 410 411 /// ARM EHABI Section 6.2 - The generic model 412 /// 413 /// An exception-handling table entry for the generic model is laid out as: 414 /// 415 /// 3 3 416 /// 1 0 0 417 /// +-+------------------------------+ 418 /// |0| personality routine offset | 419 /// +-+------------------------------+ 420 /// | personality routine data ... | 421 /// 422 /// 423 /// ARM EHABI Section 6.3 - The ARM-defined compact model 424 /// 425 /// An exception-handling table entry for the compact model looks like: 426 /// 427 /// 3 3 2 2 2 2 428 /// 1 0 8 7 4 3 0 429 /// +-+---+----+-----------------------+ 430 /// |1| 0 | Ix | data for pers routine | 431 /// +-+---+----+-----------------------+ 432 /// | more personality routine data | 433 434 const support::ulittle32_t Word = 435 *reinterpret_cast<const support::ulittle32_t *>(Contents->data() + TableEntryOffset); 436 437 if (Word & 0x80000000) { 438 SW.printString("Model", StringRef("Compact")); 439 440 unsigned PersonalityIndex = (Word & 0x0f000000) >> 24; 441 SW.printNumber("PersonalityIndex", PersonalityIndex); 442 443 switch (PersonalityIndex) { 444 case AEABI_UNWIND_CPP_PR0: 445 PrintOpcodes(Contents->data() + TableEntryOffset, 3, 1); 446 break; 447 case AEABI_UNWIND_CPP_PR1: 448 case AEABI_UNWIND_CPP_PR2: 449 unsigned AdditionalWords = (Word & 0x00ff0000) >> 16; 450 PrintOpcodes(Contents->data() + TableEntryOffset, 2 + 4 * AdditionalWords, 451 2); 452 break; 453 } 454 } else { 455 SW.printString("Model", StringRef("Generic")); 456 457 uint64_t Address = PREL31(Word, EHT->sh_addr); 458 SW.printHex("PersonalityRoutineAddress", Address); 459 if (ErrorOr<StringRef> Name = FunctionAtAddress(EHT->sh_link, Address)) 460 SW.printString("PersonalityRoutineName", *Name); 461 } 462 } 463 464 template <typename ET> 465 void PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry, 466 size_t Length, off_t Offset) const { 467 ListScope OCC(SW, "Opcodes"); 468 OpcodeDecoder(OCC.W).Decode(Entry, Offset, Length); 469 } 470 471 template <typename ET> 472 void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex, 473 const Elf_Shdr *IT) const { 474 ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(IT); 475 if (!Contents) 476 return; 477 478 /// ARM EHABI Section 5 - Index Table Entries 479 /// * The first word contains a PREL31 offset to the start of a function with 480 /// bit 31 clear 481 /// * The second word contains one of: 482 /// - The PREL31 offset of the start of the table entry for the function, 483 /// with bit 31 clear 484 /// - The exception-handling table entry itself with bit 31 set 485 /// - The special bit pattern EXIDX_CANTUNWIND, indicating that associated 486 /// frames cannot be unwound 487 488 const support::ulittle32_t *Data = 489 reinterpret_cast<const support::ulittle32_t *>(Contents->data()); 490 const unsigned Entries = IT->sh_size / IndexTableEntrySize; 491 492 ListScope E(SW, "Entries"); 493 for (unsigned Entry = 0; Entry < Entries; ++Entry) { 494 DictScope E(SW, "Entry"); 495 496 const support::ulittle32_t Word0 = 497 Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 0]; 498 const support::ulittle32_t Word1 = 499 Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 1]; 500 501 if (Word0 & 0x80000000) { 502 errs() << "corrupt unwind data in section " << SectionIndex << "\n"; 503 continue; 504 } 505 506 const uint64_t Offset = PREL31(Word0, IT->sh_addr); 507 SW.printHex("FunctionAddress", Offset); 508 if (ErrorOr<StringRef> Name = FunctionAtAddress(IT->sh_link, Offset)) 509 SW.printString("FunctionName", *Name); 510 511 if (Word1 == EXIDX_CANTUNWIND) { 512 SW.printString("Model", StringRef("CantUnwind")); 513 continue; 514 } 515 516 if (Word1 & 0x80000000) { 517 SW.printString("Model", StringRef("Compact (Inline)")); 518 519 unsigned PersonalityIndex = (Word1 & 0x0f000000) >> 24; 520 SW.printNumber("PersonalityIndex", PersonalityIndex); 521 522 PrintOpcodes(Contents->data() + Entry * IndexTableEntrySize + 4, 3, 1); 523 } else { 524 const Elf_Shdr *EHT = 525 FindExceptionTable(SectionIndex, Entry * IndexTableEntrySize + 4); 526 527 if (ErrorOr<StringRef> Name = ELF->getSectionName(EHT)) 528 SW.printString("ExceptionHandlingTable", *Name); 529 530 uint64_t TableEntryOffset = PREL31(Word1, IT->sh_addr); 531 SW.printHex("TableEntryOffset", TableEntryOffset); 532 533 PrintExceptionTable(IT, EHT, TableEntryOffset); 534 } 535 } 536 } 537 538 template <typename ET> 539 void PrinterContext<ET>::PrintUnwindInformation() const { 540 DictScope UI(SW, "UnwindInformation"); 541 542 int SectionIndex = 0; 543 for (const Elf_Shdr &Sec : ELF->sections()) { 544 if (Sec.sh_type == ELF::SHT_ARM_EXIDX) { 545 DictScope UIT(SW, "UnwindIndexTable"); 546 547 SW.printNumber("SectionIndex", SectionIndex); 548 if (ErrorOr<StringRef> SectionName = ELF->getSectionName(&Sec)) 549 SW.printString("SectionName", *SectionName); 550 SW.printHex("SectionOffset", Sec.sh_offset); 551 552 PrintIndexTable(SectionIndex, &Sec); 553 } 554 ++SectionIndex; 555 } 556 } 557 } 558 } 559 } 560 561 #endif 562 563