1 //===--- ARMEHABIPrinter.h - ARM EHABI Unwind Information Printer ----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H
11 #define LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H
14 #include "llvm-readobj.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/Object/ELF.h"
17 #include "llvm/Object/ELFTypes.h"
18 #include "llvm/Support/ARMEHABI.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/Endian.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/ScopedPrinter.h"
23 #include "llvm/Support/type_traits.h"
36 void (OpcodeDecoder::*Routine
)(const uint8_t *Opcodes
, unsigned &OI
);
38 static ArrayRef
<RingEntry
> ring();
40 void Decode_00xxxxxx(const uint8_t *Opcodes
, unsigned &OI
);
41 void Decode_01xxxxxx(const uint8_t *Opcodes
, unsigned &OI
);
42 void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes
, unsigned &OI
);
43 void Decode_10011101(const uint8_t *Opcodes
, unsigned &OI
);
44 void Decode_10011111(const uint8_t *Opcodes
, unsigned &OI
);
45 void Decode_1001nnnn(const uint8_t *Opcodes
, unsigned &OI
);
46 void Decode_10100nnn(const uint8_t *Opcodes
, unsigned &OI
);
47 void Decode_10101nnn(const uint8_t *Opcodes
, unsigned &OI
);
48 void Decode_10110000(const uint8_t *Opcodes
, unsigned &OI
);
49 void Decode_10110001_0000iiii(const uint8_t *Opcodes
, unsigned &OI
);
50 void Decode_10110010_uleb128(const uint8_t *Opcodes
, unsigned &OI
);
51 void Decode_10110011_sssscccc(const uint8_t *Opcodes
, unsigned &OI
);
52 void Decode_101101nn(const uint8_t *Opcodes
, unsigned &OI
);
53 void Decode_10111nnn(const uint8_t *Opcodes
, unsigned &OI
);
54 void Decode_11000110_sssscccc(const uint8_t *Opcodes
, unsigned &OI
);
55 void Decode_11000111_0000iiii(const uint8_t *Opcodes
, unsigned &OI
);
56 void Decode_11001000_sssscccc(const uint8_t *Opcodes
, unsigned &OI
);
57 void Decode_11001001_sssscccc(const uint8_t *Opcodes
, unsigned &OI
);
58 void Decode_11001yyy(const uint8_t *Opcodes
, unsigned &OI
);
59 void Decode_11000nnn(const uint8_t *Opcodes
, unsigned &OI
);
60 void Decode_11010nnn(const uint8_t *Opcodes
, unsigned &OI
);
61 void Decode_11xxxyyy(const uint8_t *Opcodes
, unsigned &OI
);
63 void PrintGPR(uint16_t GPRMask
);
64 void PrintRegisters(uint32_t Mask
, StringRef Prefix
);
67 OpcodeDecoder(ScopedPrinter
&SW
) : SW(SW
), OS(SW
.getOStream()) {}
68 void Decode(const uint8_t *Opcodes
, off_t Offset
, size_t Length
);
71 inline ArrayRef
<OpcodeDecoder::RingEntry
> OpcodeDecoder::ring() {
72 static const OpcodeDecoder::RingEntry Ring
[] = {
73 {0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx
},
74 {0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx
},
75 {0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii
},
76 {0xff, 0x9d, &OpcodeDecoder::Decode_10011101
},
77 {0xff, 0x9f, &OpcodeDecoder::Decode_10011111
},
78 {0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn
},
79 {0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn
},
80 {0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn
},
81 {0xff, 0xb0, &OpcodeDecoder::Decode_10110000
},
82 {0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii
},
83 {0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128
},
84 {0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc
},
85 {0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn
},
86 {0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn
},
87 {0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc
},
88 {0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii
},
89 {0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc
},
90 {0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc
},
91 {0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy
},
92 {0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn
},
93 {0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn
},
94 {0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy
},
96 return makeArrayRef(Ring
);
99 inline void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes
,
101 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
102 SW
.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode
,
103 ((Opcode
& 0x3f) << 2) + 4);
105 inline void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes
,
107 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
108 SW
.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode
,
109 ((Opcode
& 0x3f) << 2) + 4);
111 inline void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes
,
113 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
114 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
116 uint16_t GPRMask
= (Opcode1
<< 4) | ((Opcode0
& 0x0f) << 12);
118 << format("0x%02X 0x%02X ; %s",
119 Opcode0
, Opcode1
, GPRMask
? "pop " : "refuse to unwind");
124 inline void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes
,
126 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
127 SW
.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode
);
129 inline void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes
,
131 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
132 SW
.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode
);
134 inline void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes
,
136 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
137 SW
.startLine() << format("0x%02X ; vsp = r%u\n", Opcode
, (Opcode
& 0x0f));
139 inline void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes
,
141 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
142 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
143 PrintGPR((((1 << ((Opcode
& 0x7) + 1)) - 1) << 4));
146 inline void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes
,
148 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
149 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
150 PrintGPR((((1 << ((Opcode
& 0x7) + 1)) - 1) << 4) | (1 << 14));
153 inline void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes
,
155 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
156 SW
.startLine() << format("0x%02X ; finish\n", Opcode
);
158 inline void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes
,
160 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
161 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
164 << format("0x%02X 0x%02X ; %s", Opcode0
, Opcode1
,
165 ((Opcode1
& 0xf0) || Opcode1
== 0x00) ? "spare" : "pop ");
166 if (((Opcode1
& 0xf0) == 0x00) && Opcode1
)
167 PrintGPR((Opcode1
& 0x0f));
170 inline void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes
,
172 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
173 SW
.startLine() << format("0x%02X ", Opcode
);
175 SmallVector
<uint8_t, 4> ULEB
;
176 do { ULEB
.push_back(Opcodes
[OI
^ 3]); } while (Opcodes
[OI
++ ^ 3] & 0x80);
178 for (unsigned BI
= 0, BE
= ULEB
.size(); BI
!= BE
; ++BI
)
179 OS
<< format("0x%02X ", ULEB
[BI
]);
182 for (unsigned BI
= 0, BE
= ULEB
.size(); BI
!= BE
; ++BI
)
183 Value
= Value
| ((ULEB
[BI
] & 0x7f) << (7 * BI
));
185 OS
<< format("; vsp = vsp + %" PRIu64
"\n", 0x204 + (Value
<< 2));
187 inline void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes
,
189 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
190 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
191 SW
.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0
, Opcode1
);
192 uint8_t Start
= ((Opcode1
& 0xf0) >> 4);
193 uint8_t Count
= ((Opcode1
& 0x0f) >> 0);
194 PrintRegisters((((1 << (Count
+ 1)) - 1) << Start
), "d");
197 inline void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes
,
199 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
200 SW
.startLine() << format("0x%02X ; spare\n", Opcode
);
202 inline void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes
,
204 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
205 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
206 PrintRegisters((((1 << ((Opcode
& 0x07) + 1)) - 1) << 8), "d");
209 inline void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes
,
211 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
212 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
213 SW
.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0
, Opcode1
);
214 uint8_t Start
= ((Opcode1
& 0xf0) >> 4);
215 uint8_t Count
= ((Opcode1
& 0x0f) >> 0);
216 PrintRegisters((((1 << (Count
+ 1)) - 1) << Start
), "wR");
219 inline void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes
,
221 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
222 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
224 << format("0x%02X 0x%02X ; %s", Opcode0
, Opcode1
,
225 ((Opcode1
& 0xf0) || Opcode1
== 0x00) ? "spare" : "pop ");
226 if ((Opcode1
& 0xf0) == 0x00 && Opcode1
)
227 PrintRegisters(Opcode1
& 0x0f, "wCGR");
230 inline void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes
,
232 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
233 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
234 SW
.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0
, Opcode1
);
235 uint8_t Start
= 16 + ((Opcode1
& 0xf0) >> 4);
236 uint8_t Count
= ((Opcode1
& 0x0f) >> 0);
237 PrintRegisters((((1 << (Count
+ 1)) - 1) << Start
), "d");
240 inline void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes
,
242 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
243 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
244 SW
.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0
, Opcode1
);
245 uint8_t Start
= ((Opcode1
& 0xf0) >> 4);
246 uint8_t Count
= ((Opcode1
& 0x0f) >> 0);
247 PrintRegisters((((1 << (Count
+ 1)) - 1) << Start
), "d");
250 inline void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes
,
252 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
253 SW
.startLine() << format("0x%02X ; spare\n", Opcode
);
255 inline void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes
,
257 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
258 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
259 PrintRegisters((((1 << ((Opcode
& 0x07) + 1)) - 1) << 10), "wR");
262 inline void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes
,
264 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
265 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
266 PrintRegisters((((1 << ((Opcode
& 0x07) + 1)) - 1) << 8), "d");
269 inline void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes
,
271 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
272 SW
.startLine() << format("0x%02X ; spare\n", Opcode
);
275 inline void OpcodeDecoder::PrintGPR(uint16_t GPRMask
) {
276 static const char *GPRRegisterNames
[16] = {
277 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
278 "fp", "ip", "sp", "lr", "pc"
283 for (unsigned RI
= 0, RE
= 17; RI
< RE
; ++RI
) {
284 if (GPRMask
& (1 << RI
)) {
287 OS
<< GPRRegisterNames
[RI
];
294 inline void OpcodeDecoder::PrintRegisters(uint32_t VFPMask
, StringRef Prefix
) {
297 for (unsigned RI
= 0, RE
= 32; RI
< RE
; ++RI
) {
298 if (VFPMask
& (1 << RI
)) {
308 inline void OpcodeDecoder::Decode(const uint8_t *Opcodes
, off_t Offset
,
310 for (unsigned OCI
= Offset
; OCI
< Length
+ Offset
; ) {
311 bool Decoded
= false;
312 for (const auto &RE
: ring()) {
313 if ((Opcodes
[OCI
^ 3] & RE
.Mask
) == RE
.Value
) {
314 (this->*RE
.Routine
)(Opcodes
, OCI
);
320 SW
.startLine() << format("0x%02X ; reserved\n", Opcodes
[OCI
++ ^ 3]);
324 template <typename ET
>
325 class PrinterContext
{
326 typedef typename
ET::Sym Elf_Sym
;
327 typedef typename
ET::Shdr Elf_Shdr
;
328 typedef typename
ET::Rel Elf_Rel
;
329 typedef typename
ET::Word Elf_Word
;
332 const object::ELFFile
<ET
> *ELF
;
333 const Elf_Shdr
*Symtab
;
334 ArrayRef
<Elf_Word
> ShndxTable
;
336 static const size_t IndexTableEntrySize
;
338 static uint64_t PREL31(uint32_t Address
, uint32_t Place
) {
339 uint64_t Location
= Address
& 0x7fffffff;
340 if (Location
& 0x04000000)
341 Location
|= (uint64_t) ~0x7fffffff;
342 return Location
+ Place
;
345 ErrorOr
<StringRef
> FunctionAtAddress(unsigned Section
, uint64_t Address
) const;
346 const Elf_Shdr
*FindExceptionTable(unsigned IndexTableIndex
,
347 off_t IndexTableOffset
) const;
349 void PrintIndexTable(unsigned SectionIndex
, const Elf_Shdr
*IT
) const;
350 void PrintExceptionTable(const Elf_Shdr
*IT
, const Elf_Shdr
*EHT
,
351 uint64_t TableEntryOffset
) const;
352 void PrintOpcodes(const uint8_t *Entry
, size_t Length
, off_t Offset
) const;
355 PrinterContext(ScopedPrinter
&SW
, const object::ELFFile
<ET
> *ELF
,
356 const Elf_Shdr
*Symtab
)
357 : SW(SW
), ELF(ELF
), Symtab(Symtab
) {}
359 void PrintUnwindInformation() const;
362 template <typename ET
>
363 const size_t PrinterContext
<ET
>::IndexTableEntrySize
= 8;
365 template <typename ET
>
367 PrinterContext
<ET
>::FunctionAtAddress(unsigned Section
,
368 uint64_t Address
) const {
369 auto StrTableOrErr
= ELF
->getStringTableForSymtab(*Symtab
);
371 error(StrTableOrErr
.takeError());
372 StringRef StrTable
= *StrTableOrErr
;
374 for (const Elf_Sym
&Sym
: unwrapOrError(ELF
->symbols(Symtab
)))
375 if (Sym
.st_shndx
== Section
&& Sym
.st_value
== Address
&&
376 Sym
.getType() == ELF::STT_FUNC
) {
377 auto NameOrErr
= Sym
.getName(StrTable
);
379 // TODO: Actually report errors helpfully.
380 consumeError(NameOrErr
.takeError());
381 return readobj_error::unknown_symbol
;
385 return readobj_error::unknown_symbol
;
388 template <typename ET
>
389 const typename
ET::Shdr
*
390 PrinterContext
<ET
>::FindExceptionTable(unsigned IndexSectionIndex
,
391 off_t IndexTableOffset
) const {
392 /// Iterate through the sections, searching for the relocation section
393 /// associated with the unwind index table section specified by
394 /// IndexSectionIndex. Iterate the associated section searching for the
395 /// relocation associated with the index table entry specified by
396 /// IndexTableOffset. The symbol is the section symbol for the exception
397 /// handling table. Use this symbol to recover the actual exception handling
400 for (const Elf_Shdr
&Sec
: unwrapOrError(ELF
->sections())) {
401 if (Sec
.sh_type
!= ELF::SHT_REL
|| Sec
.sh_info
!= IndexSectionIndex
)
404 auto SymTabOrErr
= ELF
->getSection(Sec
.sh_link
);
406 error(SymTabOrErr
.takeError());
407 const Elf_Shdr
*SymTab
= *SymTabOrErr
;
409 for (const Elf_Rel
&R
: unwrapOrError(ELF
->rels(&Sec
))) {
410 if (R
.r_offset
!= static_cast<unsigned>(IndexTableOffset
))
413 typename
ET::Rela RelA
;
414 RelA
.r_offset
= R
.r_offset
;
415 RelA
.r_info
= R
.r_info
;
418 const Elf_Sym
*Symbol
=
419 unwrapOrError(ELF
->getRelocationSymbol(&RelA
, SymTab
));
421 auto Ret
= ELF
->getSection(Symbol
, SymTab
, ShndxTable
);
423 report_fatal_error(errorToErrorCode(Ret
.takeError()).message());
430 template <typename ET
>
431 void PrinterContext
<ET
>::PrintExceptionTable(const Elf_Shdr
*IT
,
433 uint64_t TableEntryOffset
) const {
434 Expected
<ArrayRef
<uint8_t>> Contents
= ELF
->getSectionContents(EHT
);
438 /// ARM EHABI Section 6.2 - The generic model
440 /// An exception-handling table entry for the generic model is laid out as:
444 /// +-+------------------------------+
445 /// |0| personality routine offset |
446 /// +-+------------------------------+
447 /// | personality routine data ... |
450 /// ARM EHABI Section 6.3 - The ARM-defined compact model
452 /// An exception-handling table entry for the compact model looks like:
456 /// +-+---+----+-----------------------+
457 /// |1| 0 | Ix | data for pers routine |
458 /// +-+---+----+-----------------------+
459 /// | more personality routine data |
461 const support::ulittle32_t Word
=
462 *reinterpret_cast<const support::ulittle32_t
*>(Contents
->data() + TableEntryOffset
);
464 if (Word
& 0x80000000) {
465 SW
.printString("Model", StringRef("Compact"));
467 unsigned PersonalityIndex
= (Word
& 0x0f000000) >> 24;
468 SW
.printNumber("PersonalityIndex", PersonalityIndex
);
470 switch (PersonalityIndex
) {
471 case AEABI_UNWIND_CPP_PR0
:
472 PrintOpcodes(Contents
->data() + TableEntryOffset
, 3, 1);
474 case AEABI_UNWIND_CPP_PR1
:
475 case AEABI_UNWIND_CPP_PR2
:
476 unsigned AdditionalWords
= (Word
& 0x00ff0000) >> 16;
477 PrintOpcodes(Contents
->data() + TableEntryOffset
, 2 + 4 * AdditionalWords
,
482 SW
.printString("Model", StringRef("Generic"));
484 uint64_t Address
= PREL31(Word
, EHT
->sh_addr
);
485 SW
.printHex("PersonalityRoutineAddress", Address
);
486 if (ErrorOr
<StringRef
> Name
= FunctionAtAddress(EHT
->sh_link
, Address
))
487 SW
.printString("PersonalityRoutineName", *Name
);
491 template <typename ET
>
492 void PrinterContext
<ET
>::PrintOpcodes(const uint8_t *Entry
,
493 size_t Length
, off_t Offset
) const {
494 ListScope
OCC(SW
, "Opcodes");
495 OpcodeDecoder(OCC
.W
).Decode(Entry
, Offset
, Length
);
498 template <typename ET
>
499 void PrinterContext
<ET
>::PrintIndexTable(unsigned SectionIndex
,
500 const Elf_Shdr
*IT
) const {
501 Expected
<ArrayRef
<uint8_t>> Contents
= ELF
->getSectionContents(IT
);
505 /// ARM EHABI Section 5 - Index Table Entries
506 /// * The first word contains a PREL31 offset to the start of a function with
508 /// * The second word contains one of:
509 /// - The PREL31 offset of the start of the table entry for the function,
510 /// with bit 31 clear
511 /// - The exception-handling table entry itself with bit 31 set
512 /// - The special bit pattern EXIDX_CANTUNWIND, indicating that associated
513 /// frames cannot be unwound
515 const support::ulittle32_t
*Data
=
516 reinterpret_cast<const support::ulittle32_t
*>(Contents
->data());
517 const unsigned Entries
= IT
->sh_size
/ IndexTableEntrySize
;
519 ListScope
E(SW
, "Entries");
520 for (unsigned Entry
= 0; Entry
< Entries
; ++Entry
) {
521 DictScope
E(SW
, "Entry");
523 const support::ulittle32_t Word0
=
524 Data
[Entry
* (IndexTableEntrySize
/ sizeof(*Data
)) + 0];
525 const support::ulittle32_t Word1
=
526 Data
[Entry
* (IndexTableEntrySize
/ sizeof(*Data
)) + 1];
528 if (Word0
& 0x80000000) {
529 errs() << "corrupt unwind data in section " << SectionIndex
<< "\n";
533 const uint64_t Offset
= PREL31(Word0
, IT
->sh_addr
);
534 SW
.printHex("FunctionAddress", Offset
);
535 if (ErrorOr
<StringRef
> Name
= FunctionAtAddress(IT
->sh_link
, Offset
))
536 SW
.printString("FunctionName", *Name
);
538 if (Word1
== EXIDX_CANTUNWIND
) {
539 SW
.printString("Model", StringRef("CantUnwind"));
543 if (Word1
& 0x80000000) {
544 SW
.printString("Model", StringRef("Compact (Inline)"));
546 unsigned PersonalityIndex
= (Word1
& 0x0f000000) >> 24;
547 SW
.printNumber("PersonalityIndex", PersonalityIndex
);
549 PrintOpcodes(Contents
->data() + Entry
* IndexTableEntrySize
+ 4, 3, 1);
551 const Elf_Shdr
*EHT
=
552 FindExceptionTable(SectionIndex
, Entry
* IndexTableEntrySize
+ 4);
554 if (auto Name
= ELF
->getSectionName(EHT
))
555 SW
.printString("ExceptionHandlingTable", *Name
);
557 uint64_t TableEntryOffset
= PREL31(Word1
, IT
->sh_addr
);
558 SW
.printHex("TableEntryOffset", TableEntryOffset
);
560 PrintExceptionTable(IT
, EHT
, TableEntryOffset
);
565 template <typename ET
>
566 void PrinterContext
<ET
>::PrintUnwindInformation() const {
567 DictScope
UI(SW
, "UnwindInformation");
569 int SectionIndex
= 0;
570 for (const Elf_Shdr
&Sec
: unwrapOrError(ELF
->sections())) {
571 if (Sec
.sh_type
== ELF::SHT_ARM_EXIDX
) {
572 DictScope
UIT(SW
, "UnwindIndexTable");
574 SW
.printNumber("SectionIndex", SectionIndex
);
575 if (auto SectionName
= ELF
->getSectionName(&Sec
))
576 SW
.printString("SectionName", *SectionName
);
577 SW
.printHex("SectionOffset", Sec
.sh_offset
);
579 PrintIndexTable(SectionIndex
, &Sec
);