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
;
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 StringRef FileName
, const Elf_Shdr
*Symtab
)
357 : SW(SW
), ELF(ELF
), FileName(FileName
), 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 {
370 return readobj_error::unknown_symbol
;
371 auto StrTableOrErr
= ELF
->getStringTableForSymtab(*Symtab
);
373 reportError(StrTableOrErr
.takeError(), FileName
);
374 StringRef StrTable
= *StrTableOrErr
;
376 for (const Elf_Sym
&Sym
: unwrapOrError(FileName
, ELF
->symbols(Symtab
)))
377 if (Sym
.st_shndx
== Section
&& Sym
.st_value
== Address
&&
378 Sym
.getType() == ELF::STT_FUNC
) {
379 auto NameOrErr
= Sym
.getName(StrTable
);
381 // TODO: Actually report errors helpfully.
382 consumeError(NameOrErr
.takeError());
383 return readobj_error::unknown_symbol
;
387 return readobj_error::unknown_symbol
;
390 template <typename ET
>
391 const typename
ET::Shdr
*
392 PrinterContext
<ET
>::FindExceptionTable(unsigned IndexSectionIndex
,
393 off_t IndexTableOffset
) const {
394 /// Iterate through the sections, searching for the relocation section
395 /// associated with the unwind index table section specified by
396 /// IndexSectionIndex. Iterate the associated section searching for the
397 /// relocation associated with the index table entry specified by
398 /// IndexTableOffset. The symbol is the section symbol for the exception
399 /// handling table. Use this symbol to recover the actual exception handling
402 for (const Elf_Shdr
&Sec
: unwrapOrError(FileName
, ELF
->sections())) {
403 if (Sec
.sh_type
!= ELF::SHT_REL
|| Sec
.sh_info
!= IndexSectionIndex
)
406 auto SymTabOrErr
= ELF
->getSection(Sec
.sh_link
);
408 reportError(SymTabOrErr
.takeError(), FileName
);
409 const Elf_Shdr
*SymTab
= *SymTabOrErr
;
411 for (const Elf_Rel
&R
: unwrapOrError(FileName
, ELF
->rels(&Sec
))) {
412 if (R
.r_offset
!= static_cast<unsigned>(IndexTableOffset
))
415 typename
ET::Rela RelA
;
416 RelA
.r_offset
= R
.r_offset
;
417 RelA
.r_info
= R
.r_info
;
420 const Elf_Sym
*Symbol
=
421 unwrapOrError(FileName
, ELF
->getRelocationSymbol(&RelA
, SymTab
));
423 auto Ret
= ELF
->getSection(Symbol
, SymTab
, ShndxTable
);
425 report_fatal_error(errorToErrorCode(Ret
.takeError()).message());
432 template <typename ET
>
433 void PrinterContext
<ET
>::PrintExceptionTable(const Elf_Shdr
*IT
,
435 uint64_t TableEntryOffset
) const {
436 Expected
<ArrayRef
<uint8_t>> Contents
= ELF
->getSectionContents(EHT
);
440 /// ARM EHABI Section 6.2 - The generic model
442 /// An exception-handling table entry for the generic model is laid out as:
446 /// +-+------------------------------+
447 /// |0| personality routine offset |
448 /// +-+------------------------------+
449 /// | personality routine data ... |
452 /// ARM EHABI Section 6.3 - The ARM-defined compact model
454 /// An exception-handling table entry for the compact model looks like:
458 /// +-+---+----+-----------------------+
459 /// |1| 0 | Ix | data for pers routine |
460 /// +-+---+----+-----------------------+
461 /// | more personality routine data |
463 const support::ulittle32_t Word
=
464 *reinterpret_cast<const support::ulittle32_t
*>(Contents
->data() + TableEntryOffset
);
466 if (Word
& 0x80000000) {
467 SW
.printString("Model", StringRef("Compact"));
469 unsigned PersonalityIndex
= (Word
& 0x0f000000) >> 24;
470 SW
.printNumber("PersonalityIndex", PersonalityIndex
);
472 switch (PersonalityIndex
) {
473 case AEABI_UNWIND_CPP_PR0
:
474 PrintOpcodes(Contents
->data() + TableEntryOffset
, 3, 1);
476 case AEABI_UNWIND_CPP_PR1
:
477 case AEABI_UNWIND_CPP_PR2
:
478 unsigned AdditionalWords
= (Word
& 0x00ff0000) >> 16;
479 PrintOpcodes(Contents
->data() + TableEntryOffset
, 2 + 4 * AdditionalWords
,
484 SW
.printString("Model", StringRef("Generic"));
486 uint64_t Address
= PREL31(Word
, EHT
->sh_addr
);
487 SW
.printHex("PersonalityRoutineAddress", Address
);
488 if (ErrorOr
<StringRef
> Name
= FunctionAtAddress(EHT
->sh_link
, Address
))
489 SW
.printString("PersonalityRoutineName", *Name
);
493 template <typename ET
>
494 void PrinterContext
<ET
>::PrintOpcodes(const uint8_t *Entry
,
495 size_t Length
, off_t Offset
) const {
496 ListScope
OCC(SW
, "Opcodes");
497 OpcodeDecoder(OCC
.W
).Decode(Entry
, Offset
, Length
);
500 template <typename ET
>
501 void PrinterContext
<ET
>::PrintIndexTable(unsigned SectionIndex
,
502 const Elf_Shdr
*IT
) const {
503 Expected
<ArrayRef
<uint8_t>> Contents
= ELF
->getSectionContents(IT
);
507 /// ARM EHABI Section 5 - Index Table Entries
508 /// * The first word contains a PREL31 offset to the start of a function with
510 /// * The second word contains one of:
511 /// - The PREL31 offset of the start of the table entry for the function,
512 /// with bit 31 clear
513 /// - The exception-handling table entry itself with bit 31 set
514 /// - The special bit pattern EXIDX_CANTUNWIND, indicating that associated
515 /// frames cannot be unwound
517 const support::ulittle32_t
*Data
=
518 reinterpret_cast<const support::ulittle32_t
*>(Contents
->data());
519 const unsigned Entries
= IT
->sh_size
/ IndexTableEntrySize
;
521 ListScope
E(SW
, "Entries");
522 for (unsigned Entry
= 0; Entry
< Entries
; ++Entry
) {
523 DictScope
E(SW
, "Entry");
525 const support::ulittle32_t Word0
=
526 Data
[Entry
* (IndexTableEntrySize
/ sizeof(*Data
)) + 0];
527 const support::ulittle32_t Word1
=
528 Data
[Entry
* (IndexTableEntrySize
/ sizeof(*Data
)) + 1];
530 if (Word0
& 0x80000000) {
531 errs() << "corrupt unwind data in section " << SectionIndex
<< "\n";
535 const uint64_t Offset
= PREL31(Word0
, IT
->sh_addr
);
536 SW
.printHex("FunctionAddress", Offset
);
537 if (ErrorOr
<StringRef
> Name
= FunctionAtAddress(IT
->sh_link
, Offset
))
538 SW
.printString("FunctionName", *Name
);
540 if (Word1
== EXIDX_CANTUNWIND
) {
541 SW
.printString("Model", StringRef("CantUnwind"));
545 if (Word1
& 0x80000000) {
546 SW
.printString("Model", StringRef("Compact (Inline)"));
548 unsigned PersonalityIndex
= (Word1
& 0x0f000000) >> 24;
549 SW
.printNumber("PersonalityIndex", PersonalityIndex
);
551 PrintOpcodes(Contents
->data() + Entry
* IndexTableEntrySize
+ 4, 3, 1);
553 const Elf_Shdr
*EHT
=
554 FindExceptionTable(SectionIndex
, Entry
* IndexTableEntrySize
+ 4);
557 if (auto Name
= ELF
->getSectionName(EHT
))
558 SW
.printString("ExceptionHandlingTable", *Name
);
560 uint64_t TableEntryOffset
= PREL31(Word1
, IT
->sh_addr
);
561 SW
.printHex("TableEntryOffset", TableEntryOffset
);
564 PrintExceptionTable(IT
, EHT
, TableEntryOffset
);
569 template <typename ET
>
570 void PrinterContext
<ET
>::PrintUnwindInformation() const {
571 DictScope
UI(SW
, "UnwindInformation");
573 int SectionIndex
= 0;
574 for (const Elf_Shdr
&Sec
: unwrapOrError(FileName
, ELF
->sections())) {
575 if (Sec
.sh_type
== ELF::SHT_ARM_EXIDX
) {
576 DictScope
UIT(SW
, "UnwindIndexTable");
578 SW
.printNumber("SectionIndex", SectionIndex
);
579 if (auto SectionName
= ELF
->getSectionName(&Sec
))
580 SW
.printString("SectionName", *SectionName
);
581 SW
.printHex("SectionOffset", Sec
.sh_offset
);
583 PrintIndexTable(SectionIndex
, &Sec
);