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