1 //===--- ARMEHABIPrinter.h - ARM EHABI Unwind Information Printer ----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H
10 #define LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H
13 #include "llvm-readobj.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/Object/ELF.h"
16 #include "llvm/Object/ELFTypes.h"
17 #include "llvm/Support/ARMEHABI.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/Endian.h"
20 #include "llvm/Support/Format.h"
21 #include "llvm/Support/ScopedPrinter.h"
22 #include "llvm/Support/type_traits.h"
35 void (OpcodeDecoder::*Routine
)(const uint8_t *Opcodes
, unsigned &OI
);
37 static ArrayRef
<RingEntry
> ring();
39 void Decode_00xxxxxx(const uint8_t *Opcodes
, unsigned &OI
);
40 void Decode_01xxxxxx(const uint8_t *Opcodes
, unsigned &OI
);
41 void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes
, unsigned &OI
);
42 void Decode_10011101(const uint8_t *Opcodes
, unsigned &OI
);
43 void Decode_10011111(const uint8_t *Opcodes
, unsigned &OI
);
44 void Decode_1001nnnn(const uint8_t *Opcodes
, unsigned &OI
);
45 void Decode_10100nnn(const uint8_t *Opcodes
, unsigned &OI
);
46 void Decode_10101nnn(const uint8_t *Opcodes
, unsigned &OI
);
47 void Decode_10110000(const uint8_t *Opcodes
, unsigned &OI
);
48 void Decode_10110001_0000iiii(const uint8_t *Opcodes
, unsigned &OI
);
49 void Decode_10110010_uleb128(const uint8_t *Opcodes
, unsigned &OI
);
50 void Decode_10110011_sssscccc(const uint8_t *Opcodes
, unsigned &OI
);
51 void Decode_101101nn(const uint8_t *Opcodes
, unsigned &OI
);
52 void Decode_10111nnn(const uint8_t *Opcodes
, unsigned &OI
);
53 void Decode_11000110_sssscccc(const uint8_t *Opcodes
, unsigned &OI
);
54 void Decode_11000111_0000iiii(const uint8_t *Opcodes
, unsigned &OI
);
55 void Decode_11001000_sssscccc(const uint8_t *Opcodes
, unsigned &OI
);
56 void Decode_11001001_sssscccc(const uint8_t *Opcodes
, unsigned &OI
);
57 void Decode_11001yyy(const uint8_t *Opcodes
, unsigned &OI
);
58 void Decode_11000nnn(const uint8_t *Opcodes
, unsigned &OI
);
59 void Decode_11010nnn(const uint8_t *Opcodes
, unsigned &OI
);
60 void Decode_11xxxyyy(const uint8_t *Opcodes
, unsigned &OI
);
62 void PrintGPR(uint16_t GPRMask
);
63 void PrintRegisters(uint32_t Mask
, StringRef Prefix
);
66 OpcodeDecoder(ScopedPrinter
&SW
) : SW(SW
), OS(SW
.getOStream()) {}
67 void Decode(const uint8_t *Opcodes
, off_t Offset
, size_t Length
);
70 inline ArrayRef
<OpcodeDecoder::RingEntry
> OpcodeDecoder::ring() {
71 static const OpcodeDecoder::RingEntry Ring
[] = {
72 {0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx
},
73 {0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx
},
74 {0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii
},
75 {0xff, 0x9d, &OpcodeDecoder::Decode_10011101
},
76 {0xff, 0x9f, &OpcodeDecoder::Decode_10011111
},
77 {0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn
},
78 {0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn
},
79 {0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn
},
80 {0xff, 0xb0, &OpcodeDecoder::Decode_10110000
},
81 {0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii
},
82 {0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128
},
83 {0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc
},
84 {0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn
},
85 {0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn
},
86 {0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc
},
87 {0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii
},
88 {0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc
},
89 {0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc
},
90 {0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy
},
91 {0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn
},
92 {0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn
},
93 {0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy
},
95 return makeArrayRef(Ring
);
98 inline void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes
,
100 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
101 SW
.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode
,
102 ((Opcode
& 0x3f) << 2) + 4);
104 inline void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes
,
106 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
107 SW
.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode
,
108 ((Opcode
& 0x3f) << 2) + 4);
110 inline void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes
,
112 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
113 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
115 uint16_t GPRMask
= (Opcode1
<< 4) | ((Opcode0
& 0x0f) << 12);
117 << format("0x%02X 0x%02X ; %s",
118 Opcode0
, Opcode1
, GPRMask
? "pop " : "refuse to unwind");
123 inline void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes
,
125 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
126 SW
.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode
);
128 inline void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes
,
130 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
131 SW
.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode
);
133 inline void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes
,
135 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
136 SW
.startLine() << format("0x%02X ; vsp = r%u\n", Opcode
, (Opcode
& 0x0f));
138 inline void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes
,
140 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
141 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
142 PrintGPR((((1 << ((Opcode
& 0x7) + 1)) - 1) << 4));
145 inline void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes
,
147 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
148 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
149 PrintGPR((((1 << ((Opcode
& 0x7) + 1)) - 1) << 4) | (1 << 14));
152 inline void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes
,
154 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
155 SW
.startLine() << format("0x%02X ; finish\n", Opcode
);
157 inline void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes
,
159 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
160 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
163 << format("0x%02X 0x%02X ; %s", Opcode0
, Opcode1
,
164 ((Opcode1
& 0xf0) || Opcode1
== 0x00) ? "spare" : "pop ");
165 if (((Opcode1
& 0xf0) == 0x00) && Opcode1
)
166 PrintGPR((Opcode1
& 0x0f));
169 inline void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes
,
171 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
172 SW
.startLine() << format("0x%02X ", Opcode
);
174 SmallVector
<uint8_t, 4> ULEB
;
175 do { ULEB
.push_back(Opcodes
[OI
^ 3]); } while (Opcodes
[OI
++ ^ 3] & 0x80);
177 for (unsigned BI
= 0, BE
= ULEB
.size(); BI
!= BE
; ++BI
)
178 OS
<< format("0x%02X ", ULEB
[BI
]);
181 for (unsigned BI
= 0, BE
= ULEB
.size(); BI
!= BE
; ++BI
)
182 Value
= Value
| ((ULEB
[BI
] & 0x7f) << (7 * BI
));
184 OS
<< format("; vsp = vsp + %" PRIu64
"\n", 0x204 + (Value
<< 2));
186 inline void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes
,
188 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
189 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
190 SW
.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0
, Opcode1
);
191 uint8_t Start
= ((Opcode1
& 0xf0) >> 4);
192 uint8_t Count
= ((Opcode1
& 0x0f) >> 0);
193 PrintRegisters((((1 << (Count
+ 1)) - 1) << Start
), "d");
196 inline void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes
,
198 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
199 SW
.startLine() << format("0x%02X ; spare\n", Opcode
);
201 inline void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes
,
203 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
204 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
205 PrintRegisters((((1 << ((Opcode
& 0x07) + 1)) - 1) << 8), "d");
208 inline void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes
,
210 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
211 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
212 SW
.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0
, Opcode1
);
213 uint8_t Start
= ((Opcode1
& 0xf0) >> 4);
214 uint8_t Count
= ((Opcode1
& 0x0f) >> 0);
215 PrintRegisters((((1 << (Count
+ 1)) - 1) << Start
), "wR");
218 inline void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes
,
220 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
221 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
223 << format("0x%02X 0x%02X ; %s", Opcode0
, Opcode1
,
224 ((Opcode1
& 0xf0) || Opcode1
== 0x00) ? "spare" : "pop ");
225 if ((Opcode1
& 0xf0) == 0x00 && Opcode1
)
226 PrintRegisters(Opcode1
& 0x0f, "wCGR");
229 inline void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes
,
231 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
232 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
233 SW
.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0
, Opcode1
);
234 uint8_t Start
= 16 + ((Opcode1
& 0xf0) >> 4);
235 uint8_t Count
= ((Opcode1
& 0x0f) >> 0);
236 PrintRegisters((((1 << (Count
+ 1)) - 1) << Start
), "d");
239 inline void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes
,
241 uint8_t Opcode0
= Opcodes
[OI
++ ^ 3];
242 uint8_t Opcode1
= Opcodes
[OI
++ ^ 3];
243 SW
.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0
, Opcode1
);
244 uint8_t Start
= ((Opcode1
& 0xf0) >> 4);
245 uint8_t Count
= ((Opcode1
& 0x0f) >> 0);
246 PrintRegisters((((1 << (Count
+ 1)) - 1) << Start
), "d");
249 inline void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes
,
251 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
252 SW
.startLine() << format("0x%02X ; spare\n", Opcode
);
254 inline void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes
,
256 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
257 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
258 PrintRegisters((((1 << ((Opcode
& 0x07) + 1)) - 1) << 10), "wR");
261 inline void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes
,
263 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
264 SW
.startLine() << format("0x%02X ; pop ", Opcode
);
265 PrintRegisters((((1 << ((Opcode
& 0x07) + 1)) - 1) << 8), "d");
268 inline void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes
,
270 uint8_t Opcode
= Opcodes
[OI
++ ^ 3];
271 SW
.startLine() << format("0x%02X ; spare\n", Opcode
);
274 inline void OpcodeDecoder::PrintGPR(uint16_t GPRMask
) {
275 static const char *GPRRegisterNames
[16] = {
276 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
277 "fp", "ip", "sp", "lr", "pc"
282 for (unsigned RI
= 0, RE
= 17; RI
< RE
; ++RI
) {
283 if (GPRMask
& (1 << RI
)) {
286 OS
<< GPRRegisterNames
[RI
];
293 inline void OpcodeDecoder::PrintRegisters(uint32_t VFPMask
, StringRef Prefix
) {
296 for (unsigned RI
= 0, RE
= 32; RI
< RE
; ++RI
) {
297 if (VFPMask
& (1 << RI
)) {
307 inline void OpcodeDecoder::Decode(const uint8_t *Opcodes
, off_t Offset
,
309 for (unsigned OCI
= Offset
; OCI
< Length
+ Offset
; ) {
310 bool Decoded
= false;
311 for (const auto &RE
: ring()) {
312 if ((Opcodes
[OCI
^ 3] & RE
.Mask
) == RE
.Value
) {
313 (this->*RE
.Routine
)(Opcodes
, OCI
);
319 SW
.startLine() << format("0x%02X ; reserved\n", Opcodes
[OCI
++ ^ 3]);
323 template <typename ET
>
324 class PrinterContext
{
325 typedef typename
ET::Sym Elf_Sym
;
326 typedef typename
ET::Shdr Elf_Shdr
;
327 typedef typename
ET::Rel Elf_Rel
;
328 typedef typename
ET::Word Elf_Word
;
331 const object::ELFFile
<ET
> *ELF
;
332 const Elf_Shdr
*Symtab
;
333 ArrayRef
<Elf_Word
> ShndxTable
;
335 static const size_t IndexTableEntrySize
;
337 static uint64_t PREL31(uint32_t Address
, uint32_t Place
) {
338 uint64_t Location
= Address
& 0x7fffffff;
339 if (Location
& 0x04000000)
340 Location
|= (uint64_t) ~0x7fffffff;
341 return Location
+ Place
;
344 ErrorOr
<StringRef
> FunctionAtAddress(unsigned Section
, uint64_t Address
) const;
345 const Elf_Shdr
*FindExceptionTable(unsigned IndexTableIndex
,
346 off_t IndexTableOffset
) const;
348 void PrintIndexTable(unsigned SectionIndex
, const Elf_Shdr
*IT
) const;
349 void PrintExceptionTable(const Elf_Shdr
*IT
, const Elf_Shdr
*EHT
,
350 uint64_t TableEntryOffset
) const;
351 void PrintOpcodes(const uint8_t *Entry
, size_t Length
, off_t Offset
) const;
354 PrinterContext(ScopedPrinter
&SW
, const object::ELFFile
<ET
> *ELF
,
355 const Elf_Shdr
*Symtab
)
356 : SW(SW
), ELF(ELF
), Symtab(Symtab
) {}
358 void PrintUnwindInformation() const;
361 template <typename ET
>
362 const size_t PrinterContext
<ET
>::IndexTableEntrySize
= 8;
364 template <typename ET
>
366 PrinterContext
<ET
>::FunctionAtAddress(unsigned Section
,
367 uint64_t Address
) const {
368 auto StrTableOrErr
= ELF
->getStringTableForSymtab(*Symtab
);
370 error(StrTableOrErr
.takeError());
371 StringRef StrTable
= *StrTableOrErr
;
373 for (const Elf_Sym
&Sym
: unwrapOrError(ELF
->symbols(Symtab
)))
374 if (Sym
.st_shndx
== Section
&& Sym
.st_value
== Address
&&
375 Sym
.getType() == ELF::STT_FUNC
) {
376 auto NameOrErr
= Sym
.getName(StrTable
);
378 // TODO: Actually report errors helpfully.
379 consumeError(NameOrErr
.takeError());
380 return readobj_error::unknown_symbol
;
384 return readobj_error::unknown_symbol
;
387 template <typename ET
>
388 const typename
ET::Shdr
*
389 PrinterContext
<ET
>::FindExceptionTable(unsigned IndexSectionIndex
,
390 off_t IndexTableOffset
) const {
391 /// Iterate through the sections, searching for the relocation section
392 /// associated with the unwind index table section specified by
393 /// IndexSectionIndex. Iterate the associated section searching for the
394 /// relocation associated with the index table entry specified by
395 /// IndexTableOffset. The symbol is the section symbol for the exception
396 /// handling table. Use this symbol to recover the actual exception handling
399 for (const Elf_Shdr
&Sec
: unwrapOrError(ELF
->sections())) {
400 if (Sec
.sh_type
!= ELF::SHT_REL
|| Sec
.sh_info
!= IndexSectionIndex
)
403 auto SymTabOrErr
= ELF
->getSection(Sec
.sh_link
);
405 error(SymTabOrErr
.takeError());
406 const Elf_Shdr
*SymTab
= *SymTabOrErr
;
408 for (const Elf_Rel
&R
: unwrapOrError(ELF
->rels(&Sec
))) {
409 if (R
.r_offset
!= static_cast<unsigned>(IndexTableOffset
))
412 typename
ET::Rela RelA
;
413 RelA
.r_offset
= R
.r_offset
;
414 RelA
.r_info
= R
.r_info
;
417 const Elf_Sym
*Symbol
=
418 unwrapOrError(ELF
->getRelocationSymbol(&RelA
, SymTab
));
420 auto Ret
= ELF
->getSection(Symbol
, SymTab
, ShndxTable
);
422 report_fatal_error(errorToErrorCode(Ret
.takeError()).message());
429 template <typename ET
>
430 void PrinterContext
<ET
>::PrintExceptionTable(const Elf_Shdr
*IT
,
432 uint64_t TableEntryOffset
) const {
433 Expected
<ArrayRef
<uint8_t>> Contents
= ELF
->getSectionContents(EHT
);
437 /// ARM EHABI Section 6.2 - The generic model
439 /// An exception-handling table entry for the generic model is laid out as:
443 /// +-+------------------------------+
444 /// |0| personality routine offset |
445 /// +-+------------------------------+
446 /// | personality routine data ... |
449 /// ARM EHABI Section 6.3 - The ARM-defined compact model
451 /// An exception-handling table entry for the compact model looks like:
455 /// +-+---+----+-----------------------+
456 /// |1| 0 | Ix | data for pers routine |
457 /// +-+---+----+-----------------------+
458 /// | more personality routine data |
460 const support::ulittle32_t Word
=
461 *reinterpret_cast<const support::ulittle32_t
*>(Contents
->data() + TableEntryOffset
);
463 if (Word
& 0x80000000) {
464 SW
.printString("Model", StringRef("Compact"));
466 unsigned PersonalityIndex
= (Word
& 0x0f000000) >> 24;
467 SW
.printNumber("PersonalityIndex", PersonalityIndex
);
469 switch (PersonalityIndex
) {
470 case AEABI_UNWIND_CPP_PR0
:
471 PrintOpcodes(Contents
->data() + TableEntryOffset
, 3, 1);
473 case AEABI_UNWIND_CPP_PR1
:
474 case AEABI_UNWIND_CPP_PR2
:
475 unsigned AdditionalWords
= (Word
& 0x00ff0000) >> 16;
476 PrintOpcodes(Contents
->data() + TableEntryOffset
, 2 + 4 * AdditionalWords
,
481 SW
.printString("Model", StringRef("Generic"));
483 uint64_t Address
= PREL31(Word
, EHT
->sh_addr
);
484 SW
.printHex("PersonalityRoutineAddress", Address
);
485 if (ErrorOr
<StringRef
> Name
= FunctionAtAddress(EHT
->sh_link
, Address
))
486 SW
.printString("PersonalityRoutineName", *Name
);
490 template <typename ET
>
491 void PrinterContext
<ET
>::PrintOpcodes(const uint8_t *Entry
,
492 size_t Length
, off_t Offset
) const {
493 ListScope
OCC(SW
, "Opcodes");
494 OpcodeDecoder(OCC
.W
).Decode(Entry
, Offset
, Length
);
497 template <typename ET
>
498 void PrinterContext
<ET
>::PrintIndexTable(unsigned SectionIndex
,
499 const Elf_Shdr
*IT
) const {
500 Expected
<ArrayRef
<uint8_t>> Contents
= ELF
->getSectionContents(IT
);
504 /// ARM EHABI Section 5 - Index Table Entries
505 /// * The first word contains a PREL31 offset to the start of a function with
507 /// * The second word contains one of:
508 /// - The PREL31 offset of the start of the table entry for the function,
509 /// with bit 31 clear
510 /// - The exception-handling table entry itself with bit 31 set
511 /// - The special bit pattern EXIDX_CANTUNWIND, indicating that associated
512 /// frames cannot be unwound
514 const support::ulittle32_t
*Data
=
515 reinterpret_cast<const support::ulittle32_t
*>(Contents
->data());
516 const unsigned Entries
= IT
->sh_size
/ IndexTableEntrySize
;
518 ListScope
E(SW
, "Entries");
519 for (unsigned Entry
= 0; Entry
< Entries
; ++Entry
) {
520 DictScope
E(SW
, "Entry");
522 const support::ulittle32_t Word0
=
523 Data
[Entry
* (IndexTableEntrySize
/ sizeof(*Data
)) + 0];
524 const support::ulittle32_t Word1
=
525 Data
[Entry
* (IndexTableEntrySize
/ sizeof(*Data
)) + 1];
527 if (Word0
& 0x80000000) {
528 errs() << "corrupt unwind data in section " << SectionIndex
<< "\n";
532 const uint64_t Offset
= PREL31(Word0
, IT
->sh_addr
);
533 SW
.printHex("FunctionAddress", Offset
);
534 if (ErrorOr
<StringRef
> Name
= FunctionAtAddress(IT
->sh_link
, Offset
))
535 SW
.printString("FunctionName", *Name
);
537 if (Word1
== EXIDX_CANTUNWIND
) {
538 SW
.printString("Model", StringRef("CantUnwind"));
542 if (Word1
& 0x80000000) {
543 SW
.printString("Model", StringRef("Compact (Inline)"));
545 unsigned PersonalityIndex
= (Word1
& 0x0f000000) >> 24;
546 SW
.printNumber("PersonalityIndex", PersonalityIndex
);
548 PrintOpcodes(Contents
->data() + Entry
* IndexTableEntrySize
+ 4, 3, 1);
550 const Elf_Shdr
*EHT
=
551 FindExceptionTable(SectionIndex
, Entry
* IndexTableEntrySize
+ 4);
553 if (auto Name
= ELF
->getSectionName(EHT
))
554 SW
.printString("ExceptionHandlingTable", *Name
);
556 uint64_t TableEntryOffset
= PREL31(Word1
, IT
->sh_addr
);
557 SW
.printHex("TableEntryOffset", TableEntryOffset
);
559 PrintExceptionTable(IT
, EHT
, TableEntryOffset
);
564 template <typename ET
>
565 void PrinterContext
<ET
>::PrintUnwindInformation() const {
566 DictScope
UI(SW
, "UnwindInformation");
568 int SectionIndex
= 0;
569 for (const Elf_Shdr
&Sec
: unwrapOrError(ELF
->sections())) {
570 if (Sec
.sh_type
== ELF::SHT_ARM_EXIDX
) {
571 DictScope
UIT(SW
, "UnwindIndexTable");
573 SW
.printNumber("SectionIndex", SectionIndex
);
574 if (auto SectionName
= ELF
->getSectionName(&Sec
))
575 SW
.printString("SectionName", *SectionName
);
576 SW
.printHex("SectionOffset", Sec
.sh_offset
);
578 PrintIndexTable(SectionIndex
, &Sec
);