llvm.org GIT mirror llvm / fe3b74e
tools: initial implementation of WoA EH decoding Add support to llvm-readobj to decode Windows ARM Exception Handling data. This uses the previously added datastructures to decode the information into a format that can be used by tests. This is a necessary step to add support for emitting Windows on ARM exception handling information. A fair amount of formatting inspiration is drawn from the Win64 EH printer as well as the ARM EHABI printer. This allows for a reasonably thorough look into the encoded data. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210192 91177308-0d34-0410-b5e6-96231b3b80d8 Saleem Abdulrasool 6 years ago
4 changed file(s) with 812 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 //===-- ARMWinEHPrinter.cpp - Windows on ARM EH Data Printer ----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "ARMWinEHPrinter.h"
10 #include "Error.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/Support/ARMWinEH.h"
14 #include "llvm/Support/Format.h"
15
16 using namespace llvm;
17 using namespace llvm::object;
18 using namespace llvm::support;
19
20 namespace llvm {
21 raw_ostream &operator<<(raw_ostream &OS, const ARM::WinEH::ReturnType &RT) {
22 switch (RT) {
23 case ARM::WinEH::ReturnType::RT_POP:
24 OS << "pop {pc}";
25 break;
26 case ARM::WinEH::ReturnType::RT_B:
27 OS << "b target";
28 break;
29 case ARM::WinEH::ReturnType::RT_BW:
30 OS << "b.w target";
31 break;
32 case ARM::WinEH::ReturnType::RT_NoEpilogue:
33 OS << "(no epilogue)";
34 break;
35 }
36 return OS;
37 }
38 }
39
40 static std::string formatSymbol(StringRef Name, uint64_t Address,
41 uint64_t Offset = 0) {
42 std::string Buffer;
43 raw_string_ostream OS(Buffer);
44
45 if (!Name.empty())
46 OS << Name << " ";
47
48 if (Offset)
49 OS << format("+0x%X (0x%" PRIX64 ")", Offset, Address);
50 else if (!Name.empty())
51 OS << format("(0x%" PRIX64 ")", Address);
52 else
53 OS << format("0x%" PRIX64, Address);
54
55 return OS.str();
56 }
57
58 namespace llvm {
59 namespace ARM {
60 namespace WinEH {
61 const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction);
62
63 const Decoder::RingEntry Decoder::Ring[] = {
64 { 0x80, 0x00, &Decoder::opcode_0xxxxxxx },
65 { 0xc0, 0x80, &Decoder::opcode_10Lxxxxx },
66 { 0xf0, 0xc0, &Decoder::opcode_1100xxxx },
67 { 0xf8, 0xd0, &Decoder::opcode_11010Lxx },
68 { 0xf8, 0xd8, &Decoder::opcode_11011Lxx },
69 { 0xf8, 0xe0, &Decoder::opcode_11100xxx },
70 { 0xfc, 0xe8, &Decoder::opcode_111010xx },
71 { 0xfe, 0xec, &Decoder::opcode_1110110L },
72 { 0xff, 0xee, &Decoder::opcode_11101110 },
73 { 0xff, 0xef, &Decoder::opcode_11101111 },
74 { 0xff, 0xf5, &Decoder::opcode_11110101 },
75 { 0xff, 0xf6, &Decoder::opcode_11110110 },
76 { 0xff, 0xf7, &Decoder::opcode_11110111 },
77 { 0xff, 0xf8, &Decoder::opcode_11111000 },
78 { 0xff, 0xf9, &Decoder::opcode_11111001 },
79 { 0xff, 0xfa, &Decoder::opcode_11111010 },
80 { 0xff, 0xfb, &Decoder::opcode_11111011 },
81 { 0xff, 0xfc, &Decoder::opcode_11111100 },
82 { 0xff, 0xfd, &Decoder::opcode_11111101 },
83 { 0xff, 0xfe, &Decoder::opcode_11111110 },
84 { 0xff, 0xff, &Decoder::opcode_11111111 },
85 };
86
87 void Decoder::printRegisters(const std::pair &RegisterMask) {
88 static const char * const GPRRegisterNames[16] = {
89 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
90 "r11", "ip", "sp", "lr", "pc",
91 };
92
93 const uint16_t GPRMask = std::get<0>(RegisterMask);
94 const uint16_t VFPMask = std::get<1>(RegisterMask);
95
96 OS << '{';
97 bool Comma = false;
98 for (unsigned RI = 0, RE = 11; RI < RE; ++RI) {
99 if (GPRMask & (1 << RI)) {
100 if (Comma)
101 OS << ", ";
102 OS << GPRRegisterNames[RI];
103 Comma = true;
104 }
105 }
106 for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {
107 if (VFPMask & (1 << RI)) {
108 if (Comma)
109 OS << ", ";
110 OS << "d" << unsigned(RI);
111 Comma = true;
112 }
113 }
114 for (unsigned RI = 11, RE = 16; RI < RE; ++RI) {
115 if (GPRMask & (1 << RI)) {
116 if (Comma)
117 OS << ", ";
118 OS << GPRRegisterNames[RI];
119 Comma = true;
120 }
121 }
122 OS << '}';
123 }
124
125 ErrorOr
126 Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) {
127 for (const auto &Section : COFF.sections()) {
128 uint64_t Address;
129 uint64_t Size;
130
131 if (error_code EC = Section.getAddress(Address))
132 return EC;
133 if (error_code EC = Section.getSize(Size))
134 return EC;
135
136 if (VA >= Address && (VA - Address) <= Size)
137 return Section;
138 }
139 return readobj_error::unknown_symbol;
140 }
141
142 ErrorOr Decoder::getSymbol(const COFFObjectFile &COFF,
143 uint64_t VA, bool FunctionOnly) {
144 for (const auto &Symbol : COFF.symbols()) {
145 if (FunctionOnly) {
146 SymbolRef::Type Type;
147 if (error_code EC = Symbol.getType(Type))
148 return EC;
149 if (Type != SymbolRef::ST_Function)
150 continue;
151 }
152
153 uint64_t Address;
154 if (error_code EC = Symbol.getAddress(Address))
155 return EC;
156 if (Address == VA)
157 return Symbol;
158 }
159 return readobj_error::unknown_symbol;
160 }
161
162 ErrorOr Decoder::getRelocatedSymbol(const COFFObjectFile &,
163 const SectionRef &Section,
164 uint64_t Offset) {
165 for (const auto &Relocation : Section.relocations()) {
166 uint64_t RelocationOffset;
167 if (auto Error = Relocation.getOffset(RelocationOffset))
168 return Error;
169 if (RelocationOffset == Offset)
170 return *Relocation.getSymbol();
171 }
172 return readobj_error::unknown_symbol;
173 }
174
175 bool Decoder::opcode_0xxxxxxx(const ulittle8_t *OC, unsigned &Offset,
176 unsigned Length, bool Prologue) {
177 uint8_t Imm = OC[Offset] & 0x7f;
178 SW.startLine() << format("0x%02x ; %s sp, #(%u * 4)\n",
179 OC[Offset],
180 static_cast(Prologue ? "sub" : "add"),
181 Imm);
182 ++Offset;
183 return false;
184 }
185
186 bool Decoder::opcode_10Lxxxxx(const ulittle8_t *OC, unsigned &Offset,
187 unsigned Length, bool Prologue) {
188 unsigned Link = (OC[Offset] & 0x20) >> 5;
189 uint16_t RegisterMask = (Link << (Prologue ? 14 : 15))
190 | ((OC[Offset + 0] & 0x1f) << 8)
191 | ((OC[Offset + 1] & 0xff) << 0);
192 assert((~RegisterMask & (1 << 13)) && "sp must not be set");
193 assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set");
194
195 SW.startLine() << format("0x%02x 0x%02x ; %s.w ",
196 OC[Offset + 0], OC[Offset + 1],
197 Prologue ? "push" : "pop");
198 printRegisters(std::make_pair(RegisterMask, 0));
199 OS << '\n';
200
201 ++Offset, ++Offset;
202 return false;
203 }
204
205 bool Decoder::opcode_1100xxxx(const ulittle8_t *OC, unsigned &Offset,
206 unsigned Length, bool Prologue) {
207 if (Prologue)
208 SW.startLine() << format("0x%02x ; mov r%u, sp\n",
209 OC[Offset], OC[Offset] & 0xf);
210 else
211 SW.startLine() << format("0x%02x ; mov sp, r%u\n",
212 OC[Offset], OC[Offset] & 0xf);
213 ++Offset;
214 return false;
215 }
216
217 bool Decoder::opcode_11010Lxx(const ulittle8_t *OC, unsigned &Offset,
218 unsigned Length, bool Prologue) {
219 unsigned Link = (OC[Offset] & 0x4) >> 3;
220 unsigned Count = (OC[Offset] & 0x3);
221
222 uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
223 | (((1 << (Count + 1)) - 1) << 4);
224
225 SW.startLine() << format("0x%02x ; %s ", OC[Offset],
226 Prologue ? "push" : "pop");
227 printRegisters(std::make_pair(GPRMask, 0));
228 OS << '\n';
229
230 ++Offset;
231 return false;
232 }
233
234 bool Decoder::opcode_11011Lxx(const ulittle8_t *OC, unsigned &Offset,
235 unsigned Length, bool Prologue) {
236 unsigned Link = (OC[Offset] & 0x4) >> 2;
237 unsigned Count = (OC[Offset] & 0x3) + 4;
238
239 uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
240 | (((1 << (Count + 1)) - 1) << 4);
241
242 SW.startLine() << format("0x%02x ; %s.w ", OC[Offset],
243 Prologue ? "push" : "pop");
244 printRegisters(std::make_pair(GPRMask, 0));
245 OS << '\n';
246
247 ++Offset;
248 return false;
249 }
250
251 bool Decoder::opcode_11100xxx(const ulittle8_t *OC, unsigned &Offset,
252 unsigned Length, bool Prologue) {
253 unsigned High = (OC[Offset] & 0x7);
254 uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8);
255
256 SW.startLine() << format("0x%02x ; %s ", OC[Offset],
257 Prologue ? "vpush" : "vpop");
258 printRegisters(std::make_pair(0, VFPMask));
259 OS << '\n';
260
261 ++Offset;
262 return false;
263 }
264
265 bool Decoder::opcode_111010xx(const ulittle8_t *OC, unsigned &Offset,
266 unsigned Length, bool Prologue) {
267 uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0);
268
269 SW.startLine() << format("0x%02x 0x%02x ; %s.w sp, #(%u * 4)\n",
270 OC[Offset + 0], OC[Offset + 1],
271 static_cast(Prologue ? "sub" : "add"),
272 Imm);
273
274 ++Offset, ++Offset;
275 return false;
276 }
277
278 bool Decoder::opcode_1110110L(const ulittle8_t *OC, unsigned &Offset,
279 unsigned Length, bool Prologue) {
280 uint8_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15))
281 | ((OC[Offset + 1] & 0xff) << 0);
282
283 SW.startLine() << format("0x%02x 0x%02x ; %s ", OC[Offset + 0],
284 OC[Offset + 1], Prologue ? "push" : "pop");
285 printRegisters(std::make_pair(GPRMask, 0));
286 OS << '\n';
287
288 ++Offset, ++Offset;
289 return false;
290 }
291
292 bool Decoder::opcode_11101110(const ulittle8_t *OC, unsigned &Offset,
293 unsigned Length, bool Prologue) {
294 assert(!Prologue && "may not be used in prologue");
295
296 if (OC[Offset + 1] & 0xf0)
297 SW.startLine() << format("0x%02x 0x%02x ; reserved\n",
298 OC[Offset + 0], OC[Offset + 1]);
299 else
300 SW.startLine()
301 << format("0x%02x 0x%02x ; microsoft-specific (type: %u)\n",
302 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f);
303
304 ++Offset, ++Offset;
305 return false;
306 }
307
308 bool Decoder::opcode_11101111(const ulittle8_t *OC, unsigned &Offset,
309 unsigned Length, bool Prologue) {
310 assert(!Prologue && "may not be used in prologue");
311
312 if (OC[Offset + 1] & 0xf0)
313 SW.startLine() << format("0x%02x 0x%02x ; reserved\n",
314 OC[Offset + 0], OC[Offset + 1]);
315 else
316 SW.startLine()
317 << format("0x%02x 0x%02x ; ldr.w lr, [sp], #%u\n",
318 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);
319
320 ++Offset, ++Offset;
321 return false;
322 }
323
324 bool Decoder::opcode_11110101(const ulittle8_t *OC, unsigned &Offset,
325 unsigned Length, bool Prologue) {
326 unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
327 unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
328 uint32_t VFPMask = ((1 << (End - Start)) - 1) << Start;
329
330 SW.startLine() << format("0x%02x 0x%02x ; %s ", OC[Offset + 0],
331 OC[Offset + 1], Prologue ? "vpush" : "vpop");
332 printRegisters(std::make_pair(0, VFPMask));
333 OS << '\n';
334
335 ++Offset, ++Offset;
336 return false;
337 }
338
339 bool Decoder::opcode_11110110(const ulittle8_t *OC, unsigned &Offset,
340 unsigned Length, bool Prologue) {
341 unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
342 unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
343 uint32_t VFPMask = ((1 << (End - Start)) - 1) << 16;
344
345 SW.startLine() << format("0x%02x 0x%02x ; %s ", OC[Offset + 0],
346 OC[Offset + 1], Prologue ? "vpush" : "vpop");
347 printRegisters(std::make_pair(0, VFPMask));
348 OS << '\n';
349
350 ++Offset, ++Offset;
351 return false;
352 }
353
354 bool Decoder::opcode_11110111(const ulittle8_t *OC, unsigned &Offset,
355 unsigned Length, bool Prologue) {
356 uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
357
358 SW.startLine() << format("0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n",
359 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
360 static_cast(Prologue ? "sub" : "add"),
361 Imm);
362
363 ++Offset, ++Offset, ++Offset;
364 return false;
365 }
366
367 bool Decoder::opcode_11111000(const ulittle8_t *OC, unsigned &Offset,
368 unsigned Length, bool Prologue) {
369 uint32_t Imm = (OC[Offset + 1] << 16)
370 | (OC[Offset + 2] << 8)
371 | (OC[Offset + 3] << 0);
372
373 SW.startLine()
374 << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n",
375 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
376 static_cast(Prologue ? "sub" : "add"), Imm);
377
378 ++Offset, ++Offset, ++Offset, ++Offset;
379 return false;
380 }
381
382 bool Decoder::opcode_11111001(const ulittle8_t *OC, unsigned &Offset,
383 unsigned Length, bool Prologue) {
384 uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
385
386 SW.startLine()
387 << format("0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n",
388 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
389 static_cast(Prologue ? "sub" : "add"), Imm);
390
391 ++Offset, ++Offset, ++Offset;
392 return false;
393 }
394
395 bool Decoder::opcode_11111010(const ulittle8_t *OC, unsigned &Offset,
396 unsigned Length, bool Prologue) {
397 uint32_t Imm = (OC[Offset + 1] << 16)
398 | (OC[Offset + 2] << 8)
399 | (OC[Offset + 3] << 0);
400
401 SW.startLine()
402 << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n",
403 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
404 static_cast(Prologue ? "sub" : "add"), Imm);
405
406 ++Offset, ++Offset, ++Offset, ++Offset;
407 return false;
408 }
409
410 bool Decoder::opcode_11111011(const ulittle8_t *OC, unsigned &Offset,
411 unsigned Length, bool Prologue) {
412 SW.startLine() << format("0x%02x ; nop\n", OC[Offset]);
413 ++Offset;
414 return false;
415 }
416
417 bool Decoder::opcode_11111100(const ulittle8_t *OC, unsigned &Offset,
418 unsigned Length, bool Prologue) {
419 SW.startLine() << format("0x%02x ; nop.w\n", OC[Offset]);
420 ++Offset;
421 return false;
422 }
423
424 bool Decoder::opcode_11111101(const ulittle8_t *OC, unsigned &Offset,
425 unsigned Length, bool Prologue) {
426 SW.startLine() << format("0x%02x ; b\n", OC[Offset]);
427 ++Offset;
428 return true;
429 }
430
431 bool Decoder::opcode_11111110(const ulittle8_t *OC, unsigned &Offset,
432 unsigned Length, bool Prologue) {
433 SW.startLine() << format("0x%02x ; b.w\n", OC[Offset]);
434 ++Offset;
435 return true;
436 }
437
438 bool Decoder::opcode_11111111(const ulittle8_t *OC, unsigned &Offset,
439 unsigned Length, bool Prologue) {
440 ++Offset;
441 return true;
442 }
443
444 void Decoder::decodeOpcodes(ArrayRef Opcodes, unsigned Offset,
445 bool Prologue) {
446 assert(!Prologue || Offset == 0 && "prologue should always use offset 0");
447
448 bool Terminated = false;
449 for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) {
450 bool Decoded = false;
451 for (unsigned DI = 0, DE = array_lengthof(Ring); DI < DE; ++DI) {
452 if ((Opcodes[OI] & Ring[DI].Mask) == Ring[DI].Value) {
453 Terminated = (this->*Ring[DI].Routine)(Opcodes.data(), OI, 0, Prologue);
454 Decoded = true;
455 break;
456 }
457 }
458 assert(Decoded && "unhandled opcode");
459 }
460 }
461
462 bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
463 const SectionRef &Section,
464 uint64_t FunctionAddress, uint64_t VA) {
465 ArrayRef Contents;
466 if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
467 return false;
468
469 uint64_t SectionVA;
470 if (Section.getAddress(SectionVA))
471 return false;
472
473 uint64_t Offset = VA - SectionVA;
474 const ulittle32_t *Data =
475 reinterpret_cast(Contents.data() + Offset);
476 const ExceptionDataRecord XData(Data);
477
478 DictScope XRS(SW, "ExceptionData");
479 SW.printNumber("FunctionLength", XData.FunctionLength() << 1);
480 SW.printNumber("Version", XData.Vers());
481 SW.printBoolean("ExceptionData", XData.X());
482 SW.printBoolean("EpiloguePacked", XData.E());
483 SW.printBoolean("Fragment", XData.F());
484 SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes",
485 XData.EpilogueCount());
486 SW.printNumber("ByteCodeLength",
487 static_cast(XData.CodeWords() * sizeof(uint32_t)));
488
489 if (XData.E()) {
490 ArrayRef UC = XData.UnwindByteCode();
491 if (!XData.F()) {
492 ListScope PS(SW, "Prologue");
493 decodeOpcodes(UC, 0, /*Prologue=*/true);
494 }
495 if (XData.EpilogueCount()) {
496 ListScope ES(SW, "Epilogue");
497 decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false);
498 }
499 } else {
500 ArrayRef EpilogueScopes = XData.EpilogueScopes();
501 ListScope ESS(SW, "EpilogueScopes");
502 for (const EpilogueScope ES : EpilogueScopes) {
503 DictScope ESES(SW, "EpilogueScope");
504 SW.printNumber("StartOffset", ES.EpilogueStartOffset());
505 SW.printNumber("Condition", ES.Condition());
506 SW.printNumber("EpilogueStartIndex", ES.EpilogueStartIndex());
507
508 ListScope Opcodes(SW, "Opcodes");
509 decodeOpcodes(XData.UnwindByteCode(), ES.EpilogueStartIndex(),
510 /*Prologue=*/false);
511 }
512 }
513
514 if (XData.X()) {
515 const uint32_t Address = XData.ExceptionHandlerRVA();
516 const uint32_t Parameter = XData.ExceptionHandlerParameter();
517 const size_t HandlerOffset = HeaderWords(XData)
518 + (XData.E() ? 0 : XData.EpilogueCount())
519 + XData.CodeWords();
520
521 ErrorOr Symbol =
522 getRelocatedSymbol(COFF, Section, HandlerOffset * sizeof(uint32_t));
523 if (!Symbol)
524 Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true);
525
526 StringRef Name;
527 if (Symbol)
528 Symbol->getName(Name);
529
530 ListScope EHS(SW, "ExceptionHandler");
531 SW.printString("Routine", formatSymbol(Name, Address));
532 SW.printHex("Parameter", Parameter);
533 }
534
535 return true;
536 }
537
538 bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
539 const SectionRef Section, uint64_t Offset,
540 unsigned Index, const RuntimeFunction &RF) {
541 assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
542 "packed entry cannot be treated as an unpacked entry");
543
544 ErrorOr Function = getRelocatedSymbol(COFF, Section, Offset);
545 if (!Function)
546 Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
547
548 ErrorOr XDataRecord = getRelocatedSymbol(COFF, Section, Offset + 4);
549 if (!XDataRecord)
550 XDataRecord = getSymbol(COFF, RF.ExceptionInformationRVA());
551
552 if (!RF.BeginAddress && !Function)
553 return false;
554 if (!RF.UnwindData && !XDataRecord)
555 return false;
556
557 StringRef FunctionName;
558 uint64_t FunctionAddress;
559 if (Function) {
560 Function->getName(FunctionName);
561 Function->getAddress(FunctionAddress);
562 } else {
563 const pe32_header *PEHeader;
564 if (COFF.getPE32Header(PEHeader))
565 return false;
566 FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
567 }
568
569 SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
570
571 if (XDataRecord) {
572 StringRef Name;
573 uint64_t Address;
574
575 XDataRecord->getName(Name);
576 XDataRecord->getAddress(Address);
577
578 SW.printString("ExceptionRecord", formatSymbol(Name, Address));
579
580 section_iterator SI = COFF.section_end();
581 if (XDataRecord->getSection(SI))
582 return false;
583
584 return dumpXDataRecord(COFF, *SI, FunctionAddress, Address);
585 } else {
586 const pe32_header *PEHeader;
587 if (COFF.getPE32Header(PEHeader))
588 return false;
589
590 uint64_t Address = PEHeader->ImageBase + RF.ExceptionInformationRVA();
591 SW.printString("ExceptionRecord", formatSymbol("", Address));
592
593 ErrorOr Section =
594 getSectionContaining(COFF, RF.ExceptionInformationRVA());
595 if (!Section)
596 return false;
597
598 return dumpXDataRecord(COFF, *Section, FunctionAddress,
599 RF.ExceptionInformationRVA());
600 }
601 }
602
603 bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
604 const SectionRef Section, uint64_t Offset,
605 unsigned Index, const RuntimeFunction &RF) {
606 assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
607 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
608 "unpacked entry cannot be treated as a packed entry");
609
610 ErrorOr Function = getRelocatedSymbol(COFF, Section, Offset);
611 if (!Function)
612 Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
613
614 StringRef FunctionName;
615 uint64_t FunctionAddress;
616 if (Function) {
617 Function->getName(FunctionName);
618 Function->getAddress(FunctionAddress);
619 } else {
620 const pe32_header *PEHeader;
621 if (COFF.getPE32Header(PEHeader))
622 return false;
623 FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
624 }
625
626 SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
627 SW.printBoolean("Fragment",
628 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
629 SW.printNumber("FunctionLength", RF.FunctionLength());
630 SW.startLine() << "ReturnType: " << RF.Ret() << '\n';
631 SW.printBoolean("HomedParameters", RF.H());
632 SW.startLine() << "SavedRegisters: ";
633 printRegisters(SavedRegisterMask(RF));
634 OS << '\n';
635 SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2);
636
637 return true;
638 }
639
640 bool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF,
641 const SectionRef Section, unsigned Index,
642 ArrayRef Contents) {
643 uint64_t Offset = PDataEntrySize * Index;
644 const ulittle32_t *Data =
645 reinterpret_cast(Contents.data() + Offset);
646
647 const RuntimeFunction Entry(Data);
648 DictScope RFS(SW, "RuntimeFunction");
649 if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked)
650 return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry);
651 return dumpPackedEntry(COFF, Section, Offset, Index, Entry);
652 }
653
654 void Decoder::dumpProcedureData(const COFFObjectFile &COFF,
655 const SectionRef Section) {
656 ArrayRef Contents;
657 if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
658 return;
659
660 if (Contents.size() % PDataEntrySize) {
661 errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n";
662 return;
663 }
664
665 for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI)
666 if (!dumpProcedureDataEntry(COFF, Section, EI, Contents))
667 break;
668 }
669
670 error_code Decoder::dumpProcedureData(const COFFObjectFile &COFF) {
671 for (const auto &Section : COFF.sections()) {
672 StringRef SectionName;
673 if (error_code EC = COFF.getSectionName(COFF.getCOFFSection(Section),
674 SectionName))
675 return EC;
676
677 if (SectionName.startswith(".pdata"))
678 dumpProcedureData(COFF, Section);
679 }
680 return error_code();
681 }
682 }
683 }
684 }
685
0 //===--- ARMWinEHPrinter.h - Windows on ARM Unwind Information Printer ----===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_READOBJ_ARMWINEHPRINTER_H
10 #define LLVM_READOBJ_ARMWINEHPRINTER_H
11
12 #include "StreamWriter.h"
13 #include "llvm/object/COFF.h"
14 #include "llvm/Support/ErrorOr.h"
15
16 namespace llvm {
17 namespace ARM {
18 namespace WinEH {
19 class RuntimeFunction;
20
21 class Decoder {
22 static const size_t PDataEntrySize;
23
24 StreamWriter &SW;
25 raw_ostream &OS;
26
27 struct RingEntry {
28 uint8_t Mask;
29 uint8_t Value;
30 bool (Decoder::*Routine)(const support::ulittle8_t *, unsigned &, unsigned,
31 bool);
32 };
33 static const RingEntry Ring[];
34
35 bool opcode_0xxxxxxx(const support::ulittle8_t *Opcodes, unsigned &Offset,
36 unsigned Length, bool Prologue);
37 bool opcode_10Lxxxxx(const support::ulittle8_t *Opcodes, unsigned &Offset,
38 unsigned Length, bool Prologue);
39 bool opcode_1100xxxx(const support::ulittle8_t *Opcodes, unsigned &Offset,
40 unsigned Length, bool Prologue);
41 bool opcode_11010Lxx(const support::ulittle8_t *Opcodes, unsigned &Offset,
42 unsigned Length, bool Prologue);
43 bool opcode_11011Lxx(const support::ulittle8_t *Opcodes, unsigned &Offset,
44 unsigned Length, bool Prologue);
45 bool opcode_11100xxx(const support::ulittle8_t *Opcodes, unsigned &Offset,
46 unsigned Length, bool Prologue);
47 bool opcode_111010xx(const support::ulittle8_t *Opcodes, unsigned &Offset,
48 unsigned Length, bool Prologue);
49 bool opcode_1110110L(const support::ulittle8_t *Opcodes, unsigned &Offset,
50 unsigned Length, bool Prologue);
51 bool opcode_11101110(const support::ulittle8_t *Opcodes, unsigned &Offset,
52 unsigned Length, bool Prologue);
53 bool opcode_11101111(const support::ulittle8_t *Opcodes, unsigned &Offset,
54 unsigned Length, bool Prologue);
55 bool opcode_11110101(const support::ulittle8_t *Opcodes, unsigned &Offset,
56 unsigned Length, bool Prologue);
57 bool opcode_11110110(const support::ulittle8_t *Opcodes, unsigned &Offset,
58 unsigned Length, bool Prologue);
59 bool opcode_11110111(const support::ulittle8_t *Opcodes, unsigned &Offset,
60 unsigned Length, bool Prologue);
61 bool opcode_11111000(const support::ulittle8_t *Opcodes, unsigned &Offset,
62 unsigned Length, bool Prologue);
63 bool opcode_11111001(const support::ulittle8_t *Opcodes, unsigned &Offset,
64 unsigned Length, bool Prologue);
65 bool opcode_11111010(const support::ulittle8_t *Opcodes, unsigned &Offset,
66 unsigned Length, bool Prologue);
67 bool opcode_11111011(const support::ulittle8_t *Opcodes, unsigned &Offset,
68 unsigned Length, bool Prologue);
69 bool opcode_11111100(const support::ulittle8_t *Opcodes, unsigned &Offset,
70 unsigned Length, bool Prologue);
71 bool opcode_11111101(const support::ulittle8_t *Opcodes, unsigned &Offset,
72 unsigned Length, bool Prologue);
73 bool opcode_11111110(const support::ulittle8_t *Opcodes, unsigned &Offset,
74 unsigned Length, bool Prologue);
75 bool opcode_11111111(const support::ulittle8_t *Opcodes, unsigned &Offset,
76 unsigned Length, bool Prologue);
77
78 void decodeOpcodes(ArrayRef Opcodes, unsigned Offset,
79 bool Prologue);
80
81 void printRegisters(const std::pair &RegisterMask);
82
83 ErrorOr
84 getSectionContaining(const object::COFFObjectFile &COFF, uint64_t Address);
85
86 ErrorOr
87 getSymbol(const object::COFFObjectFile &COFF, uint64_t Address,
88 bool FunctionOnly = false);
89
90 ErrorOr
91 getRelocatedSymbol(const object::COFFObjectFile &COFF,
92 const object::SectionRef &Section, uint64_t Offset);
93
94 bool dumpXDataRecord(const object::COFFObjectFile &COFF,
95 const object::SectionRef &Section,
96 uint64_t FunctionAddress, uint64_t VA);
97 bool dumpUnpackedEntry(const object::COFFObjectFile &COFF,
98 const object::SectionRef Section, uint64_t Offset,
99 unsigned Index, const RuntimeFunction &Entry);
100 bool dumpPackedEntry(const object::COFFObjectFile &COFF,
101 const object::SectionRef Section, uint64_t Offset,
102 unsigned Index, const RuntimeFunction &Entry);
103 bool dumpProcedureDataEntry(const object::COFFObjectFile &COFF,
104 const object::SectionRef Section, unsigned Entry,
105 ArrayRef Contents);
106 void dumpProcedureData(const object::COFFObjectFile &COFF,
107 const object::SectionRef Section);
108
109 public:
110 Decoder(StreamWriter &SW) : SW(SW), OS(SW.getOStream()) {}
111 error_code dumpProcedureData(const object::COFFObjectFile &COFF);
112 };
113 }
114 }
115 }
116
117 #endif
118
55
66 add_llvm_tool(llvm-readobj
77 ARMAttributeParser.cpp
8 ARMWinEHPrinter.cpp
89 COFFDumper.cpp
910 ELFDumper.cpp
1011 Error.cpp
1515 #include "Error.h"
1616 #include "ObjDumper.h"
1717 #include "StreamWriter.h"
18 #include "ARMWinEHPrinter.h"
1819 #include "Win64EHDumper.h"
1920 #include "llvm/ADT/DenseMap.h"
2021 #include "llvm/ADT/SmallString.h"
857858 Dumper.printData(Ctx);
858859 break;
859860 }
861 case COFF::IMAGE_FILE_MACHINE_ARMNT: {
862 ARM::WinEH::Decoder Decoder(W);
863 Decoder.dumpProcedureData(*Obj);
864 break;
865 }
860866 default:
861867 W.printEnum("unsupported Image Machine", Header->Machine,
862868 makeArrayRef(ImageFileMachineType));