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