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