llvm.org GIT mirror llvm / 3ddcc49
tools: add a high level explanation for WoA EH data Add a brief explanation of the data section layout for the unwind data that the Windows on ARM EH models. This is simply to provide a rough idea of the layout of the code involved in the decoding of the unwinding. Details on the involved data structures are available in the associated support header. The bulk of it is related to printing out the byte-code to help validate generation of WoA EH. No functional change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210397 91177308-0d34-0410-b5e6-96231b3b80d8 Saleem Abdulrasool 6 years ago
1 changed file(s) with 81 addition(s) and 21 deletion(s). Raw diff Collapse all Expand all
55 // License. See LICENSE.TXT for details.
66 //
77 //===----------------------------------------------------------------------===//
8
9 // Windows on ARM uses a series of serialised data structures (RuntimeFunction)
10 // to create a table of information for unwinding. In order to conserve space,
11 // there are two different ways that this data is represented.
12 //
13 // For functions with canonical forms for the prologue and epilogue, the data
14 // can be stored in a "packed" form. In this case, the data is packed into the
15 // RuntimeFunction's remaining 30-bits and can fully describe the entire frame.
16 //
17 // +---------------------------------------+
18 // | Function Entry Address |
19 // +---------------------------------------+
20 // | Packed Form Data |
21 // +---------------------------------------+
22 //
23 // This layout is parsed by Decoder::dumpPackedEntry. No unwind bytecode is
24 // associated with such a frame as they can be derived from the provided data.
25 // The decoder does not synthesize this data as it is unnecessary for the
26 // purposes of validation, with the synthesis being required only by a proper
27 // unwinder.
28 //
29 // For functions that are large or do not match canonical forms, the data is
30 // split up into two portions, with the actual data residing in the "exception
31 // data" table (.xdata) with a reference to the entry from the "procedure data"
32 // (.pdata) entry.
33 //
34 // The exception data contains information about the frame setup, all of the
35 // epilouge scopes (for functions for which there are multiple exit points) and
36 // the associated exception handler. Additionally, the entry contains byte-code
37 // describing how to unwind the function (c.f. Decoder::decodeOpcodes).
38 //
39 // +---------------------------------------+
40 // | Function Entry Address |
41 // +---------------------------------------+
42 // | Exception Data Entry Address |
43 // +---------------------------------------+
44 //
45 // This layout is parsed by Decoder::dumpUnpackedEntry. Such an entry must
46 // first resolve the exception data entry address. This structure
47 // (ExceptionDataRecord) has a variable sized header
48 // (c.f. ARM::WinEH::HeaderWords) and encodes most of the same information as
49 // the packed form. However, because this information is insufficient to
50 // synthesize the unwinding, there are associated unwinding bytecode which make
51 // up the bulk of the Decoder.
52 //
53 // The decoder itself is table-driven, using the first byte to determine the
54 // opcode and dispatching to the associated printing routine. The bytecode
55 // itself is a variable length instruction encoding that can fully describe the
56 // state of the stack and the necessary operations for unwinding to the
57 // beginning of the frame.
58 //
59 // The byte-code maintains a 1-1 instruction mapping, indicating both the width
60 // of the instruction (Thumb2 instructions are variable length, 16 or 32 bits
61 // wide) allowing the program to unwind from any point in the prologue, body, or
62 // epilogue of the function.
863
964 #include "ARMWinEHPrinter.h"
1065 #include "Error.h"
60115 namespace WinEH {
61116 const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction);
62117
118 // TODO name the uops more appropriately
63119 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 },
120 { 0x80, 0x00, &Decoder::opcode_0xxxxxxx }, // UOP_STACK_FREE (16-bit)
121 { 0xc0, 0x80, &Decoder::opcode_10Lxxxxx }, // UOP_POP (32-bit)
122 { 0xf0, 0xc0, &Decoder::opcode_1100xxxx }, // UOP_STACK_SAVE (16-bit)
123 { 0xf8, 0xd0, &Decoder::opcode_11010Lxx }, // UOP_POP (16-bit)
124 { 0xf8, 0xd8, &Decoder::opcode_11011Lxx }, // UOP_POP (32-bit)
125 { 0xf8, 0xe0, &Decoder::opcode_11100xxx }, // UOP_VPOP (32-bit)
126 { 0xfc, 0xe8, &Decoder::opcode_111010xx }, // UOP_STACK_FREE (32-bit)
127 { 0xfe, 0xec, &Decoder::opcode_1110110L }, // UOP_POP (16-bit)
128 { 0xff, 0xee, &Decoder::opcode_11101110 }, // UOP_MICROSOFT_SPECIFIC (16-bit)
129 // UOP_PUSH_MACHINE_FRAME
130 // UOP_PUSH_CONTEXT
131 // UOP_PUSH_TRAP_FRAME
132 // UOP_REDZONE_RESTORE_LR
133 { 0xff, 0xef, &Decoder::opcode_11101111 }, // UOP_LDRPC_POSTINC (32-bit)
134 { 0xff, 0xf5, &Decoder::opcode_11110101 }, // UOP_VPOP (32-bit)
135 { 0xff, 0xf6, &Decoder::opcode_11110110 }, // UOP_VPOP (32-bit)
136 { 0xff, 0xf7, &Decoder::opcode_11110111 }, // UOP_STACK_RESTORE (16-bit)
137 { 0xff, 0xf8, &Decoder::opcode_11111000 }, // UOP_STACK_RESTORE (16-bit)
138 { 0xff, 0xf9, &Decoder::opcode_11111001 }, // UOP_STACK_RESTORE (32-bit)
139 { 0xff, 0xfa, &Decoder::opcode_11111010 }, // UOP_STACK_RESTORE (32-bit)
140 { 0xff, 0xfb, &Decoder::opcode_11111011 }, // UOP_NOP (16-bit)
141 { 0xff, 0xfc, &Decoder::opcode_11111100 }, // UOP_NOP (32-bit)
142 { 0xff, 0xfd, &Decoder::opcode_11111101 }, // UOP_NOP (16-bit) / END
143 { 0xff, 0xfe, &Decoder::opcode_11111110 }, // UOP_NOP (32-bit) / END
144 { 0xff, 0xff, &Decoder::opcode_11111111 }, // UOP_END
85145 };
86146
87147 void Decoder::printRegisters(const std::pair &RegisterMask) {