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