ARMEHABIPrinter.h revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===--- ARMEHABIPrinter.h - ARM EHABI Unwind Information Printer ----------===// 236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// The LLVM Compiler Infrastructure 436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This file is distributed under the University of Illinois Open Source 636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// License. See LICENSE.TXT for details. 736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===----------------------------------------------------------------------===// 936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#ifndef LLVM_READOBJ_ARMEHABI_PRINTER_H 1136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#define LLVM_READOBJ_ARMEHABI_PRINTER_H 1236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "Error.h" 1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "StreamWriter.h" 1536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Object/ELF.h" 1636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Object/ELFTypes.h" 1736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/ARMEHABI.h" 1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/Debug.h" 1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/Endian.h" 2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/Format.h" 2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/type_traits.h" 2236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesnamespace { 2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename type_, size_t N> 2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinessize_t countof(const type_ (&)[N]) { 2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return N; 2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesnamespace llvm { 3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesnamespace ARM { 3236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesnamespace EHABI { 3336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesclass OpcodeDecoder { 3536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StreamWriter &SW; 3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines raw_ostream &OS; 3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct RingEntry { 3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Mask; 4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Value; 4136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void (OpcodeDecoder::*Routine)(const uint8_t *Opcodes, unsigned &OI); 4236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines }; 4336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines static const RingEntry Ring[]; 4436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI); 4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI); 4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, unsigned &OI); 4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_10011101(const uint8_t *Opcodes, unsigned &OI); 4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_10011111(const uint8_t *Opcodes, unsigned &OI); 5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI); 5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI); 5236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI); 5336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_10110000(const uint8_t *Opcodes, unsigned &OI); 5436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_10110001_0000iiii(const uint8_t *Opcodes, unsigned &OI); 5536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_10110010_uleb128(const uint8_t *Opcodes, unsigned &OI); 5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_10110011_sssscccc(const uint8_t *Opcodes, unsigned &OI); 5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_101101nn(const uint8_t *Opcodes, unsigned &OI); 5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI); 5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_11000110_sssscccc(const uint8_t *Opcodes, unsigned &OI); 6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_11000111_0000iiii(const uint8_t *Opcodes, unsigned &OI); 6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_11001000_sssscccc(const uint8_t *Opcodes, unsigned &OI); 6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_11001001_sssscccc(const uint8_t *Opcodes, unsigned &OI); 6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI); 6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI); 6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI); 6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI); 6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void PrintGPR(uint16_t GPRMask); 6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void PrintRegisters(uint32_t Mask, StringRef Prefix); 7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinespublic: 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OpcodeDecoder(StreamWriter &SW) : SW(SW), OS(SW.getOStream()) {} 7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length); 7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}; 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst OpcodeDecoder::RingEntry OpcodeDecoder::Ring[] = { 7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx }, 7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx }, 7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii }, 8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0x9d, &OpcodeDecoder::Decode_10011101 }, 8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0x9f, &OpcodeDecoder::Decode_10011111 }, 8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn }, 8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn }, 8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn }, 8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0xb0, &OpcodeDecoder::Decode_10110000 }, 8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii }, 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128 }, 8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc }, 8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn }, 9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn }, 9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc }, 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii }, 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc }, 9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc }, 9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy }, 9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn }, 9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn }, 9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines { 0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy }, 9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}; 10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI) { 10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode, 10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ((Opcode & 0x3f) << 2) + 4); 10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI) { 10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode, 10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ((Opcode & 0x3f) << 2) + 4); 11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, 11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned &OI) { 11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12); 11736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() 11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << format("0x%02X 0x%02X ; %s", 11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind"); 12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (GPRMask) 12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintGPR(GPRMask); 12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes, unsigned &OI) { 12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode); 12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes, unsigned &OI) { 12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode); 13136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 13236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI) { 13336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f)); 13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI) { 13736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 13836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; pop ", Opcode); 13936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4)); 14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 14136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 14236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI) { 14336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; pop ", Opcode); 14536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14)); 14636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 14736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 14836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes, unsigned &OI) { 14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 15036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; finish\n", Opcode); 15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes, 15336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned &OI) { 15436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 15536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 15636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 15736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() 15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1, 15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop "); 16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (((Opcode1 & 0xf0) == 0x00) && Opcode1) 16136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintGPR((Opcode1 & 0x0f)); 16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 16336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 16436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes, 16536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned &OI) { 16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 16736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ", Opcode); 16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SmallVector<uint8_t, 4> ULEB; 17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80); 17136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI) 17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << format("0x%02X ", ULEB[BI]); 17436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 17536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Value = 0; 17636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI) 17736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI)); 17836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 17936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2)); 18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 18136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes, 18236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned &OI) { 18336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 18436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 18536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 18636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Start = ((Opcode1 & 0xf0) >> 4); 18736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Count = ((Opcode1 & 0x0f) >> 0); 18836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d"); 18936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 19036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 19136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes, unsigned &OI) { 19236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 19336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; spare\n", Opcode); 19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 19536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI) { 19636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 19736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; pop ", Opcode); 19836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d"); 19936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 20036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 20136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes, 20236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned &OI) { 20336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 20436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 20536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Start = ((Opcode1 & 0xf0) >> 4); 20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Count = ((Opcode1 & 0x0f) >> 0); 20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR"); 20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 21036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes, 21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned &OI) { 21336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 21436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 21536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() 21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1, 21736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop "); 21836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((Opcode1 & 0xf0) == 0x00 && Opcode1) 21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintRegisters(Opcode1 & 0x0f, "wCGR"); 22036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 22136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 22236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes, 22336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned &OI) { 22436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 22536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 22636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 22736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4); 22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Count = ((Opcode1 & 0x0f) >> 0); 22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d"); 23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes, 23336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned &OI) { 23436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode0 = Opcodes[OI++ ^ 3]; 23536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode1 = Opcodes[OI++ ^ 3]; 23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1); 23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Start = ((Opcode1 & 0xf0) >> 4); 23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Count = ((Opcode1 & 0x0f) >> 0); 23936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d"); 24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 24136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI) { 24336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 24436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; spare\n", Opcode); 24536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 24636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI) { 24736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 24836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; pop ", Opcode); 24936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR"); 25036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 25136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 25236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI) { 25336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 25436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; pop ", Opcode); 25536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d"); 25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '\n'; 25736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 25836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI) { 25936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t Opcode = Opcodes[OI++ ^ 3]; 26036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; spare\n", Opcode); 26136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 26236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::PrintGPR(uint16_t GPRMask) { 26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines static const char *GPRRegisterNames[16] = { 26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", 26636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "fp", "ip", "sp", "lr", "pc" 26736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines }; 26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 26936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '{'; 27036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool Comma = false; 27136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (unsigned RI = 0, RE = 17; RI < RE; ++RI) { 27236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (GPRMask & (1 << RI)) { 27336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Comma) 27436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << ", "; 27536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << GPRRegisterNames[RI]; 27636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Comma = true; 27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 27836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '}'; 28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 28136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 28236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) { 28336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '{'; 28436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool Comma = false; 28536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (unsigned RI = 0, RE = 32; RI < RE; ++RI) { 28636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (VFPMask & (1 << RI)) { 28736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Comma) 28836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << ", "; 28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << Prefix << RI; 29036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Comma = true; 29136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 29236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 29336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OS << '}'; 29436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 29536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 29636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset, size_t Length) { 29736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (unsigned OCI = Offset; OCI < Length + Offset; ) { 29836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool Decoded = false; 29936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (unsigned REI = 0, REE = countof(Ring); REI != REE && !Decoded; ++REI) { 30036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((Opcodes[OCI ^ 3] & Ring[REI].Mask) == Ring[REI].Value) { 30136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines (this->*Ring[REI].Routine)(Opcodes, OCI); 30236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Decoded = true; 30336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 30436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 30536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 30636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!Decoded) 30736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.startLine() << format("0x%02X ; reserved\n", Opcodes[OCI++ ^ 3]); 30836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 30936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 31036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 31136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename ET> 31236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesclass PrinterContext { 31336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StreamWriter &SW; 31436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const object::ELFFile<ET> *ELF; 31536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 31636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines typedef typename object::ELFFile<ET>::Elf_Sym Elf_Sym; 31736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines typedef typename object::ELFFile<ET>::Elf_Shdr Elf_Shdr; 31836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 31936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines typedef typename object::ELFFile<ET>::Elf_Rel_Iter Elf_Rel_iterator; 32036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines typedef typename object::ELFFile<ET>::Elf_Sym_Iter Elf_Sym_iterator; 32136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines typedef typename object::ELFFile<ET>::Elf_Shdr_Iter Elf_Shdr_iterator; 32236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 32336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines static const size_t IndexTableEntrySize; 32436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 32536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines static uint64_t PREL31(uint32_t Address, uint32_t Place) { 32636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Location = Address & 0x7fffffff; 32736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Location & 0x04000000) 32836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Location |= (uint64_t) ~0x7fffffff; 32936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Location + Place; 33036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 33136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 33236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ErrorOr<StringRef> FunctionAtAddress(unsigned Section, uint64_t Address) const; 33336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex, 33436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines off_t IndexTableOffset) const; 33536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *IT) const; 33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void PrintExceptionTable(const Elf_Shdr *IT, const Elf_Shdr *EHT, 33836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t TableEntryOffset) const; 33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void PrintOpcodes(const uint8_t *Entry, size_t Length, off_t Offset) const; 34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 34136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinespublic: 34236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrinterContext(StreamWriter &Writer, const object::ELFFile<ET> *File) 34336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : SW(Writer), ELF(File) {} 34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 34536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void PrintUnwindInformation() const; 34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}; 34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 34836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename ET> 34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst size_t PrinterContext<ET>::IndexTableEntrySize = 8; 35036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename ET> 35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesErrorOr<StringRef> PrinterContext<ET>::FunctionAtAddress(unsigned Section, 35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Address) const { 35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (Elf_Sym_iterator SI = ELF->begin_symbols(), SE = ELF->end_symbols(); 35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SI != SE; ++SI) 35636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (SI->st_shndx == Section && SI->st_value == Address && 35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SI->getType() == ELF::STT_FUNC) 35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ELF->getSymbolName(SI); 35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return readobj_error::unknown_symbol; 36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename ET> 36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst typename object::ELFFile<ET>::Elf_Shdr * 36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesPrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex, 36536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines off_t IndexTableOffset) const { 36636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// Iterate through the sections, searching for the relocation section 36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// associated with the unwind index table section specified by 36836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// IndexSectionIndex. Iterate the associated section searching for the 36936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// relocation associated with the index table entry specified by 37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// IndexTableOffset. The symbol is the section symbol for the exception 37136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// handling table. Use this symbol to recover the actual exception handling 37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// table. 37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 37436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (Elf_Shdr_iterator SI = ELF->begin_sections(), SE = ELF->end_sections(); 37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SI != SE; ++SI) { 37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (SI->sh_type == ELF::SHT_REL && SI->sh_info == IndexSectionIndex) { 37736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (Elf_Rel_iterator RI = ELF->begin_rel(&*SI), RE = ELF->end_rel(&*SI); 37836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RI != RE; ++RI) { 37936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (RI->r_offset == static_cast<unsigned>(IndexTableOffset)) { 38036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines typename object::ELFFile<ET>::Elf_Rela RelA; 38136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RelA.r_offset = RI->r_offset; 38236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RelA.r_info = RI->r_info; 38336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RelA.r_addend = 0; 38436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 38536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::pair<const Elf_Shdr *, const Elf_Sym *> Symbol = 38636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ELF->getRelocationSymbol(&(*SI), &RelA); 38736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 38836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ELF->getSection(Symbol.second); 38936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 39036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 39136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 39236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 39336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return NULL; 39436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 39536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 39636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename ET> 39736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr *IT, 39836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const Elf_Shdr *EHT, 39936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t TableEntryOffset) const { 40036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(EHT); 40136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!Contents) 40236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 40336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 40436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// ARM EHABI Section 6.2 - The generic model 40536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 40636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// An exception-handling table entry for the generic model is laid out as: 40736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 40836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 3 3 40936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 1 0 0 41036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// +-+------------------------------+ 41136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// |0| personality routine offset | 41236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// +-+------------------------------+ 41336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// | personality routine data ... | 41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 41536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 41636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// ARM EHABI Section 6.3 - The ARM-defined compact model 41736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 41836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// An exception-handling table entry for the compact model looks like: 41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 42036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 3 3 2 2 2 2 42136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// 1 0 8 7 4 3 0 42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// +-+---+----+-----------------------+ 42336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// |1| 0 | Ix | data for pers routine | 42436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// +-+---+----+-----------------------+ 42536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// | more personality routine data | 42636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 42736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const support::ulittle32_t Word = 42836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *reinterpret_cast<const support::ulittle32_t *>(Contents->data() + TableEntryOffset); 42936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 43036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Word & 0x80000000) { 43136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printString("Model", StringRef("Compact")); 43236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 43336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned PersonalityIndex = (Word & 0x0f000000) >> 24; 43436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printNumber("PersonalityIndex", PersonalityIndex); 43536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (PersonalityIndex) { 43736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case AEABI_UNWIND_CPP_PR0: 43836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintOpcodes(Contents->data() + TableEntryOffset, 3, 1); 43936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 44036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case AEABI_UNWIND_CPP_PR1: 44136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case AEABI_UNWIND_CPP_PR2: 44236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned AdditionalWords = (Word & 0x00ff0000) >> 16; 44336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintOpcodes(Contents->data() + TableEntryOffset, 2 + 4 * AdditionalWords, 44436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 2); 44536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 44636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 44736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 44836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printString("Model", StringRef("Generic")); 44936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 45036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Address = PREL31(Word, EHT->sh_addr); 45136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printHex("PersonalityRoutineAddress", Address); 45236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ErrorOr<StringRef> Name = FunctionAtAddress(EHT->sh_link, Address)) 45336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printString("PersonalityRoutineName", *Name); 45436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 45536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 45636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 45736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename ET> 45836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry, 45936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t Length, off_t Offset) const { 46036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ListScope OCC(SW, "Opcodes"); 46136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OpcodeDecoder(OCC.W).Decode(Entry, Offset, Length); 46236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 46336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 46436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename ET> 46536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex, 46636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const Elf_Shdr *IT) const { 46736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(IT); 46836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!Contents) 46936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 47036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 47136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// ARM EHABI Section 5 - Index Table Entries 47236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// * The first word contains a PREL31 offset to the start of a function with 47336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// bit 31 clear 47436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// * The second word contains one of: 47536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// - The PREL31 offset of the start of the table entry for the function, 47636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// with bit 31 clear 47736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// - The exception-handling table entry itself with bit 31 set 47836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// - The special bit pattern EXIDX_CANTUNWIND, indicating that associated 47936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// frames cannot be unwound 48036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 48136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const support::ulittle32_t *Data = 48236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines reinterpret_cast<const support::ulittle32_t *>(Contents->data()); 48336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const unsigned Entries = IT->sh_size / IndexTableEntrySize; 48436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 48536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ListScope E(SW, "Entries"); 48636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (unsigned Entry = 0; Entry < Entries; ++Entry) { 48736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DictScope E(SW, "Entry"); 48836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 48936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const support::ulittle32_t Word0 = 49036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 0]; 49136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const support::ulittle32_t Word1 = 49236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 1]; 49336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 49436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Word0 & 0x80000000) { 49536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines errs() << "corrupt unwind data in section " << SectionIndex << "\n"; 49636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 49736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 49836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 49936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const uint64_t Offset = PREL31(Word0, IT->sh_addr); 50036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printHex("FunctionAddress", Offset); 50136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ErrorOr<StringRef> Name = FunctionAtAddress(IT->sh_link, Offset)) 50236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printString("FunctionName", *Name); 50336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 50436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Word1 == EXIDX_CANTUNWIND) { 50536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printString("Model", StringRef("CantUnwind")); 50636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 50736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 50836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 50936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Word1 & 0x80000000) { 51036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printString("Model", StringRef("Compact (Inline)")); 51136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 51236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned PersonalityIndex = (Word1 & 0x0f000000) >> 24; 51336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printNumber("PersonalityIndex", PersonalityIndex); 51436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 51536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintOpcodes(Contents->data() + Entry * IndexTableEntrySize + 4, 3, 1); 51636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 51736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const Elf_Shdr *EHT = 51836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines FindExceptionTable(SectionIndex, Entry * IndexTableEntrySize + 4); 51936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 52036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ErrorOr<StringRef> Name = ELF->getSectionName(EHT)) 52136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printString("ExceptionHandlingTable", *Name); 52236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 52336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t TableEntryOffset = PREL31(Word1, IT->sh_addr); 52436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printHex("TableEntryOffset", TableEntryOffset); 52536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 52636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintExceptionTable(IT, EHT, TableEntryOffset); 52736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 52836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 52936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 53036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 53136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename ET> 53236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid PrinterContext<ET>::PrintUnwindInformation() const { 53336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DictScope UI(SW, "UnwindInformation"); 53436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 53536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int SectionIndex = 0; 53636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (Elf_Shdr_iterator SI = ELF->begin_sections(), SE = ELF->end_sections(); 53736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SI != SE; ++SI, ++SectionIndex) { 53836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (SI->sh_type == ELF::SHT_ARM_EXIDX) { 53936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const Elf_Shdr *IT = &(*SI); 54036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 54136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DictScope UIT(SW, "UnwindIndexTable"); 54236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 54336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printNumber("SectionIndex", SectionIndex); 54436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ErrorOr<StringRef> SectionName = ELF->getSectionName(IT)) 54536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printString("SectionName", *SectionName); 54636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SW.printHex("SectionOffset", IT->sh_offset); 54736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 54836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PrintIndexTable(SectionIndex, IT); 54936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 55036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 55136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 55236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 55336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 55436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 55536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 55636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#endif 55736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 558