1274955Ssvnmir//===--- ARMEHABIPrinter.h - ARM EHABI Unwind Information Printer ----------===// 2274955Ssvnmir// 3274955Ssvnmir// The LLVM Compiler Infrastructure 4274955Ssvnmir// 5274955Ssvnmir// This file is distributed under the University of Illinois Open Source 6274955Ssvnmir// License. See LICENSE.TXT for details. 7274955Ssvnmir// 8274955Ssvnmir//===----------------------------------------------------------------------===// 9274955Ssvnmir 10280031Sdim#ifndef LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H 11280031Sdim#define LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H 12274955Ssvnmir 13274955Ssvnmir#include "Error.h" 14274955Ssvnmir#include "StreamWriter.h" 15274955Ssvnmir#include "llvm/ADT/STLExtras.h" 16274955Ssvnmir#include "llvm/Object/ELF.h" 17274955Ssvnmir#include "llvm/Object/ELFTypes.h" 18274955Ssvnmir#include "llvm/Support/ARMEHABI.h" 19274955Ssvnmir#include "llvm/Support/Debug.h" 20274955Ssvnmir#include "llvm/Support/Endian.h" 21274955Ssvnmir#include "llvm/Support/Format.h" 22274955Ssvnmir#include "llvm/Support/type_traits.h" 23274955Ssvnmir 24274955Ssvnmirnamespace llvm { 25274955Ssvnmirnamespace ARM { 26274955Ssvnmirnamespace EHABI { 27274955Ssvnmir 28274955Ssvnmirclass OpcodeDecoder { 29274955Ssvnmir StreamWriter &SW; 30274955Ssvnmir raw_ostream &OS; 31274955Ssvnmir 32274955Ssvnmir struct RingEntry { 33274955Ssvnmir uint8_t Mask; 34274955Ssvnmir uint8_t Value; 35274955Ssvnmir void (OpcodeDecoder::*Routine)(const uint8_t *Opcodes, unsigned &OI); 36274955Ssvnmir }; 37274955Ssvnmir static const RingEntry Ring[]; 38274955Ssvnmir 39274955Ssvnmir void Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI); 40274955Ssvnmir void Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI); 41274955Ssvnmir void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, unsigned &OI); 42274955Ssvnmir void Decode_10011101(const uint8_t *Opcodes, unsigned &OI); 43274955Ssvnmir void Decode_10011111(const uint8_t *Opcodes, unsigned &OI); 44274955Ssvnmir void Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI); 45274955Ssvnmir void Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI); 46274955Ssvnmir void Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI); 47274955Ssvnmir void Decode_10110000(const uint8_t *Opcodes, unsigned &OI); 48274955Ssvnmir void Decode_10110001_0000iiii(const uint8_t *Opcodes, unsigned &OI); 49274955Ssvnmir void Decode_10110010_uleb128(const uint8_t *Opcodes, unsigned &OI); 50274955Ssvnmir void Decode_10110011_sssscccc(const uint8_t *Opcodes, unsigned &OI); 51274955Ssvnmir void Decode_101101nn(const uint8_t *Opcodes, unsigned &OI); 52274955Ssvnmir void Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI); 53274955Ssvnmir void Decode_11000110_sssscccc(const uint8_t *Opcodes, unsigned &OI); 54274955Ssvnmir void Decode_11000111_0000iiii(const uint8_t *Opcodes, unsigned &OI); 55274955Ssvnmir void Decode_11001000_sssscccc(const uint8_t *Opcodes, unsigned &OI); 56274955Ssvnmir void Decode_11001001_sssscccc(const uint8_t *Opcodes, unsigned &OI); 57274955Ssvnmir void Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI); 58274955Ssvnmir void Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI); 59274955Ssvnmir void Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI); 60274955Ssvnmir void Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI); 61274955Ssvnmir 62274955Ssvnmir void PrintGPR(uint16_t GPRMask); 63274955Ssvnmir void PrintRegisters(uint32_t Mask, StringRef Prefix); 64274955Ssvnmir 65274955Ssvnmirpublic: 66274955Ssvnmir OpcodeDecoder(StreamWriter &SW) : SW(SW), OS(SW.getOStream()) {} 67274955Ssvnmir void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length); 68274955Ssvnmir}; 69274955Ssvnmir 70274955Ssvnmirconst OpcodeDecoder::RingEntry OpcodeDecoder::Ring[] = { 71274955Ssvnmir { 0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx }, 72274955Ssvnmir { 0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx }, 73274955Ssvnmir { 0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii }, 74274955Ssvnmir { 0xff, 0x9d, &OpcodeDecoder::Decode_10011101 }, 75274955Ssvnmir { 0xff, 0x9f, &OpcodeDecoder::Decode_10011111 }, 76274955Ssvnmir { 0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn }, 77274955Ssvnmir { 0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn }, 78274955Ssvnmir { 0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn }, 79274955Ssvnmir { 0xff, 0xb0, &OpcodeDecoder::Decode_10110000 }, 80274955Ssvnmir { 0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii }, 81274955Ssvnmir { 0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128 }, 82274955Ssvnmir { 0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc }, 83274955Ssvnmir { 0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn }, 84274955Ssvnmir { 0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn }, 85274955Ssvnmir { 0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc }, 86274955Ssvnmir { 0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii }, 87274955Ssvnmir { 0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc }, 88274955Ssvnmir { 0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc }, 89274955Ssvnmir { 0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy }, 90274955Ssvnmir { 0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn }, 91274955Ssvnmir { 0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn }, 92274955Ssvnmir { 0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy }, 93274955Ssvnmir}; 94274955Ssvnmir 95274955Ssvnmirvoid OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI) { 96274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 97274955Ssvnmir SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode, 98274955Ssvnmir ((Opcode & 0x3f) << 2) + 4); 99274955Ssvnmir} 100274955Ssvnmirvoid OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI) { 101274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 102274955Ssvnmir SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode, 103274955Ssvnmir ((Opcode & 0x3f) << 2) + 4); 104274955Ssvnmir} 105274955Ssvnmirvoid OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, 106274955Ssvnmir unsigned &OI) { 107274955Ssvnmir uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 108274955Ssvnmir uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 109274955Ssvnmir 110274955Ssvnmir uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12); 111274955Ssvnmir SW.startLine() 112274955Ssvnmir << format("0x%02X 0x%02X ; %s", 113274955Ssvnmir Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind"); 114274955Ssvnmir if (GPRMask) 115274955Ssvnmir PrintGPR(GPRMask); 116274955Ssvnmir OS << '\n'; 117274955Ssvnmir} 118274955Ssvnmirvoid OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes, unsigned &OI) { 119274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 120274955Ssvnmir SW.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode); 121274955Ssvnmir} 122274955Ssvnmirvoid OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes, unsigned &OI) { 123274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 124274955Ssvnmir SW.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode); 125274955Ssvnmir} 126274955Ssvnmirvoid OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI) { 127274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 128274955Ssvnmir SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f)); 129274955Ssvnmir} 130274955Ssvnmirvoid OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI) { 131274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 132274955Ssvnmir SW.startLine() << format("0x%02X ; pop ", Opcode); 133274955Ssvnmir PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4)); 134274955Ssvnmir OS << '\n'; 135274955Ssvnmir} 136274955Ssvnmirvoid OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI) { 137274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 138274955Ssvnmir SW.startLine() << format("0x%02X ; pop ", Opcode); 139274955Ssvnmir PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14)); 140274955Ssvnmir OS << '\n'; 141274955Ssvnmir} 142274955Ssvnmirvoid OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes, unsigned &OI) { 143274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 144274955Ssvnmir SW.startLine() << format("0x%02X ; finish\n", Opcode); 145274955Ssvnmir} 146274955Ssvnmirvoid OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes, 147274955Ssvnmir unsigned &OI) { 148274955Ssvnmir uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 149274955Ssvnmir uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 150274955Ssvnmir 151274955Ssvnmir SW.startLine() 152274955Ssvnmir << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1, 153274955Ssvnmir ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop "); 154274955Ssvnmir if (((Opcode1 & 0xf0) == 0x00) && Opcode1) 155274955Ssvnmir PrintGPR((Opcode1 & 0x0f)); 156274955Ssvnmir OS << '\n'; 157274955Ssvnmir} 158274955Ssvnmirvoid OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes, 159274955Ssvnmir unsigned &OI) { 160274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 161274955Ssvnmir SW.startLine() << format("0x%02X ", Opcode); 162274955Ssvnmir 163274955Ssvnmir SmallVector<uint8_t, 4> ULEB; 164274955Ssvnmir do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80); 165274955Ssvnmir 166274955Ssvnmir for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI) 167274955Ssvnmir OS << format("0x%02X ", ULEB[BI]); 168274955Ssvnmir 169274955Ssvnmir uint64_t Value = 0; 170274955Ssvnmir for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI) 171274955Ssvnmir Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI)); 172274955Ssvnmir 173274955Ssvnmir OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2)); 174274955Ssvnmir} 175274955Ssvnmirvoid OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes, 176274955Ssvnmir unsigned &OI) { 177274955Ssvnmir uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 178274955Ssvnmir uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 179274955Ssvnmir SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 180274955Ssvnmir uint8_t Start = ((Opcode1 & 0xf0) >> 4); 181274955Ssvnmir uint8_t Count = ((Opcode1 & 0x0f) >> 0); 182274955Ssvnmir PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d"); 183274955Ssvnmir OS << '\n'; 184274955Ssvnmir} 185274955Ssvnmirvoid OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes, unsigned &OI) { 186274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 187274955Ssvnmir SW.startLine() << format("0x%02X ; spare\n", Opcode); 188274955Ssvnmir} 189274955Ssvnmirvoid OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI) { 190274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 191274955Ssvnmir SW.startLine() << format("0x%02X ; pop ", Opcode); 192274955Ssvnmir PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d"); 193274955Ssvnmir OS << '\n'; 194274955Ssvnmir} 195274955Ssvnmirvoid OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes, 196274955Ssvnmir unsigned &OI) { 197274955Ssvnmir uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 198274955Ssvnmir uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 199274955Ssvnmir SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 200274955Ssvnmir uint8_t Start = ((Opcode1 & 0xf0) >> 4); 201274955Ssvnmir uint8_t Count = ((Opcode1 & 0x0f) >> 0); 202274955Ssvnmir PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR"); 203274955Ssvnmir OS << '\n'; 204274955Ssvnmir} 205274955Ssvnmirvoid OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes, 206274955Ssvnmir unsigned &OI) { 207274955Ssvnmir uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 208274955Ssvnmir uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 209274955Ssvnmir SW.startLine() 210274955Ssvnmir << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1, 211274955Ssvnmir ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop "); 212274955Ssvnmir if ((Opcode1 & 0xf0) == 0x00 && Opcode1) 213274955Ssvnmir PrintRegisters(Opcode1 & 0x0f, "wCGR"); 214274955Ssvnmir OS << '\n'; 215274955Ssvnmir} 216274955Ssvnmirvoid OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes, 217274955Ssvnmir unsigned &OI) { 218274955Ssvnmir uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 219274955Ssvnmir uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 220274955Ssvnmir SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 221274955Ssvnmir uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4); 222274955Ssvnmir uint8_t Count = ((Opcode1 & 0x0f) >> 0); 223274955Ssvnmir PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d"); 224274955Ssvnmir OS << '\n'; 225274955Ssvnmir} 226274955Ssvnmirvoid OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes, 227274955Ssvnmir unsigned &OI) { 228274955Ssvnmir uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 229274955Ssvnmir uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 230274955Ssvnmir SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 231274955Ssvnmir uint8_t Start = ((Opcode1 & 0xf0) >> 4); 232274955Ssvnmir uint8_t Count = ((Opcode1 & 0x0f) >> 0); 233274955Ssvnmir PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d"); 234274955Ssvnmir OS << '\n'; 235274955Ssvnmir} 236274955Ssvnmirvoid OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI) { 237274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 238274955Ssvnmir SW.startLine() << format("0x%02X ; spare\n", Opcode); 239274955Ssvnmir} 240274955Ssvnmirvoid OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI) { 241274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 242274955Ssvnmir SW.startLine() << format("0x%02X ; pop ", Opcode); 243274955Ssvnmir PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR"); 244274955Ssvnmir OS << '\n'; 245274955Ssvnmir} 246274955Ssvnmirvoid OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI) { 247274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 248274955Ssvnmir SW.startLine() << format("0x%02X ; pop ", Opcode); 249274955Ssvnmir PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d"); 250274955Ssvnmir OS << '\n'; 251274955Ssvnmir} 252274955Ssvnmirvoid OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI) { 253274955Ssvnmir uint8_t Opcode = Opcodes[OI++ ^ 3]; 254274955Ssvnmir SW.startLine() << format("0x%02X ; spare\n", Opcode); 255274955Ssvnmir} 256274955Ssvnmir 257274955Ssvnmirvoid OpcodeDecoder::PrintGPR(uint16_t GPRMask) { 258274955Ssvnmir static const char *GPRRegisterNames[16] = { 259274955Ssvnmir "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", 260274955Ssvnmir "fp", "ip", "sp", "lr", "pc" 261274955Ssvnmir }; 262274955Ssvnmir 263274955Ssvnmir OS << '{'; 264274955Ssvnmir bool Comma = false; 265274955Ssvnmir for (unsigned RI = 0, RE = 17; RI < RE; ++RI) { 266274955Ssvnmir if (GPRMask & (1 << RI)) { 267274955Ssvnmir if (Comma) 268274955Ssvnmir OS << ", "; 269274955Ssvnmir OS << GPRRegisterNames[RI]; 270274955Ssvnmir Comma = true; 271274955Ssvnmir } 272274955Ssvnmir } 273274955Ssvnmir OS << '}'; 274274955Ssvnmir} 275274955Ssvnmir 276274955Ssvnmirvoid OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) { 277274955Ssvnmir OS << '{'; 278274955Ssvnmir bool Comma = false; 279274955Ssvnmir for (unsigned RI = 0, RE = 32; RI < RE; ++RI) { 280274955Ssvnmir if (VFPMask & (1 << RI)) { 281274955Ssvnmir if (Comma) 282274955Ssvnmir OS << ", "; 283274955Ssvnmir OS << Prefix << RI; 284274955Ssvnmir Comma = true; 285274955Ssvnmir } 286274955Ssvnmir } 287274955Ssvnmir OS << '}'; 288274955Ssvnmir} 289274955Ssvnmir 290274955Ssvnmirvoid OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset, size_t Length) { 291274955Ssvnmir for (unsigned OCI = Offset; OCI < Length + Offset; ) { 292274955Ssvnmir bool Decoded = false; 293274955Ssvnmir for (unsigned REI = 0, REE = array_lengthof(Ring); 294274955Ssvnmir REI != REE && !Decoded; ++REI) { 295274955Ssvnmir if ((Opcodes[OCI ^ 3] & Ring[REI].Mask) == Ring[REI].Value) { 296274955Ssvnmir (this->*Ring[REI].Routine)(Opcodes, OCI); 297274955Ssvnmir Decoded = true; 298274955Ssvnmir break; 299274955Ssvnmir } 300274955Ssvnmir } 301274955Ssvnmir if (!Decoded) 302274955Ssvnmir SW.startLine() << format("0x%02X ; reserved\n", Opcodes[OCI++ ^ 3]); 303274955Ssvnmir } 304274955Ssvnmir} 305274955Ssvnmir 306274955Ssvnmirtemplate <typename ET> 307274955Ssvnmirclass PrinterContext { 308274955Ssvnmir typedef typename object::ELFFile<ET>::Elf_Sym Elf_Sym; 309274955Ssvnmir typedef typename object::ELFFile<ET>::Elf_Shdr Elf_Shdr; 310296417Sdim typedef typename object::ELFFile<ET>::Elf_Rel Elf_Rel; 311296417Sdim typedef typename object::ELFFile<ET>::Elf_Word Elf_Word; 312274955Ssvnmir 313296417Sdim StreamWriter &SW; 314296417Sdim const object::ELFFile<ET> *ELF; 315296417Sdim const Elf_Shdr *Symtab; 316296417Sdim ArrayRef<Elf_Word> ShndxTable; 317274955Ssvnmir 318274955Ssvnmir static const size_t IndexTableEntrySize; 319274955Ssvnmir 320274955Ssvnmir static uint64_t PREL31(uint32_t Address, uint32_t Place) { 321274955Ssvnmir uint64_t Location = Address & 0x7fffffff; 322274955Ssvnmir if (Location & 0x04000000) 323274955Ssvnmir Location |= (uint64_t) ~0x7fffffff; 324274955Ssvnmir return Location + Place; 325274955Ssvnmir } 326274955Ssvnmir 327274955Ssvnmir ErrorOr<StringRef> FunctionAtAddress(unsigned Section, uint64_t Address) const; 328274955Ssvnmir const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex, 329274955Ssvnmir off_t IndexTableOffset) const; 330274955Ssvnmir 331274955Ssvnmir void PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *IT) const; 332274955Ssvnmir void PrintExceptionTable(const Elf_Shdr *IT, const Elf_Shdr *EHT, 333274955Ssvnmir uint64_t TableEntryOffset) const; 334274955Ssvnmir void PrintOpcodes(const uint8_t *Entry, size_t Length, off_t Offset) const; 335274955Ssvnmir 336274955Ssvnmirpublic: 337296417Sdim PrinterContext(StreamWriter &SW, const object::ELFFile<ET> *ELF, 338296417Sdim const Elf_Shdr *Symtab) 339296417Sdim : SW(SW), ELF(ELF), Symtab(Symtab) {} 340274955Ssvnmir 341274955Ssvnmir void PrintUnwindInformation() const; 342274955Ssvnmir}; 343274955Ssvnmir 344274955Ssvnmirtemplate <typename ET> 345274955Ssvnmirconst size_t PrinterContext<ET>::IndexTableEntrySize = 8; 346274955Ssvnmir 347274955Ssvnmirtemplate <typename ET> 348288943SdimErrorOr<StringRef> 349288943SdimPrinterContext<ET>::FunctionAtAddress(unsigned Section, 350288943Sdim uint64_t Address) const { 351296417Sdim ErrorOr<StringRef> StrTableOrErr = ELF->getStringTableForSymtab(*Symtab); 352296417Sdim error(StrTableOrErr.getError()); 353296417Sdim StringRef StrTable = *StrTableOrErr; 354296417Sdim 355296417Sdim for (const Elf_Sym &Sym : ELF->symbols(Symtab)) 356288943Sdim if (Sym.st_shndx == Section && Sym.st_value == Address && 357288943Sdim Sym.getType() == ELF::STT_FUNC) 358296417Sdim return Sym.getName(StrTable); 359274955Ssvnmir return readobj_error::unknown_symbol; 360274955Ssvnmir} 361274955Ssvnmir 362274955Ssvnmirtemplate <typename ET> 363274955Ssvnmirconst typename object::ELFFile<ET>::Elf_Shdr * 364274955SsvnmirPrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex, 365274955Ssvnmir off_t IndexTableOffset) const { 366274955Ssvnmir /// Iterate through the sections, searching for the relocation section 367274955Ssvnmir /// associated with the unwind index table section specified by 368274955Ssvnmir /// IndexSectionIndex. Iterate the associated section searching for the 369274955Ssvnmir /// relocation associated with the index table entry specified by 370274955Ssvnmir /// IndexTableOffset. The symbol is the section symbol for the exception 371274955Ssvnmir /// handling table. Use this symbol to recover the actual exception handling 372274955Ssvnmir /// table. 373274955Ssvnmir 374288943Sdim for (const Elf_Shdr &Sec : ELF->sections()) { 375296417Sdim if (Sec.sh_type != ELF::SHT_REL || Sec.sh_info != IndexSectionIndex) 376296417Sdim continue; 377274955Ssvnmir 378296417Sdim ErrorOr<const Elf_Shdr *> SymTabOrErr = ELF->getSection(Sec.sh_link); 379296417Sdim error(SymTabOrErr.getError()); 380296417Sdim const Elf_Shdr *SymTab = *SymTabOrErr; 381274955Ssvnmir 382296417Sdim for (const Elf_Rel &R : ELF->rels(&Sec)) { 383296417Sdim if (R.r_offset != static_cast<unsigned>(IndexTableOffset)) 384296417Sdim continue; 385296417Sdim 386296417Sdim typename object::ELFFile<ET>::Elf_Rela RelA; 387296417Sdim RelA.r_offset = R.r_offset; 388296417Sdim RelA.r_info = R.r_info; 389296417Sdim RelA.r_addend = 0; 390296417Sdim 391296417Sdim const Elf_Sym *Symbol = ELF->getRelocationSymbol(&RelA, SymTab); 392296417Sdim 393296417Sdim ErrorOr<const Elf_Shdr *> Ret = 394296417Sdim ELF->getSection(Symbol, SymTab, ShndxTable); 395296417Sdim if (std::error_code EC = Ret.getError()) 396296417Sdim report_fatal_error(EC.message()); 397296417Sdim return *Ret; 398274955Ssvnmir } 399274955Ssvnmir } 400274955Ssvnmir return nullptr; 401274955Ssvnmir} 402274955Ssvnmir 403274955Ssvnmirtemplate <typename ET> 404274955Ssvnmirvoid PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr *IT, 405274955Ssvnmir const Elf_Shdr *EHT, 406274955Ssvnmir uint64_t TableEntryOffset) const { 407274955Ssvnmir ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(EHT); 408274955Ssvnmir if (!Contents) 409274955Ssvnmir return; 410274955Ssvnmir 411274955Ssvnmir /// ARM EHABI Section 6.2 - The generic model 412274955Ssvnmir /// 413274955Ssvnmir /// An exception-handling table entry for the generic model is laid out as: 414274955Ssvnmir /// 415274955Ssvnmir /// 3 3 416274955Ssvnmir /// 1 0 0 417274955Ssvnmir /// +-+------------------------------+ 418274955Ssvnmir /// |0| personality routine offset | 419274955Ssvnmir /// +-+------------------------------+ 420274955Ssvnmir /// | personality routine data ... | 421274955Ssvnmir /// 422274955Ssvnmir /// 423274955Ssvnmir /// ARM EHABI Section 6.3 - The ARM-defined compact model 424274955Ssvnmir /// 425274955Ssvnmir /// An exception-handling table entry for the compact model looks like: 426274955Ssvnmir /// 427274955Ssvnmir /// 3 3 2 2 2 2 428274955Ssvnmir /// 1 0 8 7 4 3 0 429274955Ssvnmir /// +-+---+----+-----------------------+ 430274955Ssvnmir /// |1| 0 | Ix | data for pers routine | 431274955Ssvnmir /// +-+---+----+-----------------------+ 432274955Ssvnmir /// | more personality routine data | 433274955Ssvnmir 434274955Ssvnmir const support::ulittle32_t Word = 435274955Ssvnmir *reinterpret_cast<const support::ulittle32_t *>(Contents->data() + TableEntryOffset); 436274955Ssvnmir 437274955Ssvnmir if (Word & 0x80000000) { 438274955Ssvnmir SW.printString("Model", StringRef("Compact")); 439274955Ssvnmir 440274955Ssvnmir unsigned PersonalityIndex = (Word & 0x0f000000) >> 24; 441274955Ssvnmir SW.printNumber("PersonalityIndex", PersonalityIndex); 442274955Ssvnmir 443274955Ssvnmir switch (PersonalityIndex) { 444274955Ssvnmir case AEABI_UNWIND_CPP_PR0: 445274955Ssvnmir PrintOpcodes(Contents->data() + TableEntryOffset, 3, 1); 446274955Ssvnmir break; 447274955Ssvnmir case AEABI_UNWIND_CPP_PR1: 448274955Ssvnmir case AEABI_UNWIND_CPP_PR2: 449274955Ssvnmir unsigned AdditionalWords = (Word & 0x00ff0000) >> 16; 450274955Ssvnmir PrintOpcodes(Contents->data() + TableEntryOffset, 2 + 4 * AdditionalWords, 451274955Ssvnmir 2); 452274955Ssvnmir break; 453274955Ssvnmir } 454274955Ssvnmir } else { 455274955Ssvnmir SW.printString("Model", StringRef("Generic")); 456274955Ssvnmir 457274955Ssvnmir uint64_t Address = PREL31(Word, EHT->sh_addr); 458274955Ssvnmir SW.printHex("PersonalityRoutineAddress", Address); 459274955Ssvnmir if (ErrorOr<StringRef> Name = FunctionAtAddress(EHT->sh_link, Address)) 460274955Ssvnmir SW.printString("PersonalityRoutineName", *Name); 461274955Ssvnmir } 462274955Ssvnmir} 463274955Ssvnmir 464274955Ssvnmirtemplate <typename ET> 465274955Ssvnmirvoid PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry, 466274955Ssvnmir size_t Length, off_t Offset) const { 467274955Ssvnmir ListScope OCC(SW, "Opcodes"); 468274955Ssvnmir OpcodeDecoder(OCC.W).Decode(Entry, Offset, Length); 469274955Ssvnmir} 470274955Ssvnmir 471274955Ssvnmirtemplate <typename ET> 472274955Ssvnmirvoid PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex, 473274955Ssvnmir const Elf_Shdr *IT) const { 474274955Ssvnmir ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(IT); 475274955Ssvnmir if (!Contents) 476274955Ssvnmir return; 477274955Ssvnmir 478274955Ssvnmir /// ARM EHABI Section 5 - Index Table Entries 479274955Ssvnmir /// * The first word contains a PREL31 offset to the start of a function with 480274955Ssvnmir /// bit 31 clear 481274955Ssvnmir /// * The second word contains one of: 482274955Ssvnmir /// - The PREL31 offset of the start of the table entry for the function, 483274955Ssvnmir /// with bit 31 clear 484274955Ssvnmir /// - The exception-handling table entry itself with bit 31 set 485274955Ssvnmir /// - The special bit pattern EXIDX_CANTUNWIND, indicating that associated 486274955Ssvnmir /// frames cannot be unwound 487274955Ssvnmir 488274955Ssvnmir const support::ulittle32_t *Data = 489274955Ssvnmir reinterpret_cast<const support::ulittle32_t *>(Contents->data()); 490274955Ssvnmir const unsigned Entries = IT->sh_size / IndexTableEntrySize; 491274955Ssvnmir 492274955Ssvnmir ListScope E(SW, "Entries"); 493274955Ssvnmir for (unsigned Entry = 0; Entry < Entries; ++Entry) { 494274955Ssvnmir DictScope E(SW, "Entry"); 495274955Ssvnmir 496274955Ssvnmir const support::ulittle32_t Word0 = 497274955Ssvnmir Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 0]; 498274955Ssvnmir const support::ulittle32_t Word1 = 499274955Ssvnmir Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 1]; 500274955Ssvnmir 501274955Ssvnmir if (Word0 & 0x80000000) { 502274955Ssvnmir errs() << "corrupt unwind data in section " << SectionIndex << "\n"; 503274955Ssvnmir continue; 504274955Ssvnmir } 505274955Ssvnmir 506274955Ssvnmir const uint64_t Offset = PREL31(Word0, IT->sh_addr); 507274955Ssvnmir SW.printHex("FunctionAddress", Offset); 508274955Ssvnmir if (ErrorOr<StringRef> Name = FunctionAtAddress(IT->sh_link, Offset)) 509274955Ssvnmir SW.printString("FunctionName", *Name); 510274955Ssvnmir 511274955Ssvnmir if (Word1 == EXIDX_CANTUNWIND) { 512274955Ssvnmir SW.printString("Model", StringRef("CantUnwind")); 513274955Ssvnmir continue; 514274955Ssvnmir } 515274955Ssvnmir 516274955Ssvnmir if (Word1 & 0x80000000) { 517274955Ssvnmir SW.printString("Model", StringRef("Compact (Inline)")); 518274955Ssvnmir 519274955Ssvnmir unsigned PersonalityIndex = (Word1 & 0x0f000000) >> 24; 520274955Ssvnmir SW.printNumber("PersonalityIndex", PersonalityIndex); 521274955Ssvnmir 522274955Ssvnmir PrintOpcodes(Contents->data() + Entry * IndexTableEntrySize + 4, 3, 1); 523274955Ssvnmir } else { 524274955Ssvnmir const Elf_Shdr *EHT = 525274955Ssvnmir FindExceptionTable(SectionIndex, Entry * IndexTableEntrySize + 4); 526274955Ssvnmir 527274955Ssvnmir if (ErrorOr<StringRef> Name = ELF->getSectionName(EHT)) 528274955Ssvnmir SW.printString("ExceptionHandlingTable", *Name); 529274955Ssvnmir 530274955Ssvnmir uint64_t TableEntryOffset = PREL31(Word1, IT->sh_addr); 531274955Ssvnmir SW.printHex("TableEntryOffset", TableEntryOffset); 532274955Ssvnmir 533274955Ssvnmir PrintExceptionTable(IT, EHT, TableEntryOffset); 534274955Ssvnmir } 535274955Ssvnmir } 536274955Ssvnmir} 537274955Ssvnmir 538274955Ssvnmirtemplate <typename ET> 539274955Ssvnmirvoid PrinterContext<ET>::PrintUnwindInformation() const { 540274955Ssvnmir DictScope UI(SW, "UnwindInformation"); 541274955Ssvnmir 542274955Ssvnmir int SectionIndex = 0; 543288943Sdim for (const Elf_Shdr &Sec : ELF->sections()) { 544288943Sdim if (Sec.sh_type == ELF::SHT_ARM_EXIDX) { 545274955Ssvnmir DictScope UIT(SW, "UnwindIndexTable"); 546274955Ssvnmir 547274955Ssvnmir SW.printNumber("SectionIndex", SectionIndex); 548288943Sdim if (ErrorOr<StringRef> SectionName = ELF->getSectionName(&Sec)) 549274955Ssvnmir SW.printString("SectionName", *SectionName); 550288943Sdim SW.printHex("SectionOffset", Sec.sh_offset); 551274955Ssvnmir 552288943Sdim PrintIndexTable(SectionIndex, &Sec); 553274955Ssvnmir } 554288943Sdim ++SectionIndex; 555274955Ssvnmir } 556274955Ssvnmir} 557274955Ssvnmir} 558274955Ssvnmir} 559274955Ssvnmir} 560274955Ssvnmir 561274955Ssvnmir#endif 562274955Ssvnmir 563