Commit | Line | Data |
---|---|---|
284e0531 | 1 | /* seh pdata/xdata coff object file format |
2571583a | 2 | Copyright (C) 2009-2017 Free Software Foundation, Inc. |
284e0531 KT |
3 | |
4 | This file is part of GAS. | |
5 | ||
6 | GAS is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 3, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GAS is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GAS; see the file COPYING. If not, write to the Free | |
18 | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA | |
19 | 02110-1301, USA. */ | |
20 | ||
987499b2 KT |
21 | /* Short overview: |
22 | There are at the moment three different function entry formats preset. | |
23 | The first is the MIPS one. The second version | |
24 | is for ARM, PPC, SH3, and SH4 mainly for Windows CE. | |
25 | The third is the IA64 and x64 version. Note, the IA64 isn't implemented yet, | |
26 | but to find information about it, please see specification about IA64 on | |
27 | http://download.intel.com/design/Itanium/Downloads/245358.pdf file. | |
28 | ||
29 | The first version has just entries in the pdata section: BeginAddress, | |
30 | EndAddress, ExceptionHandler, HandlerData, and PrologueEndAddress. Each | |
31 | value is a pointer to the corresponding data and has size of 4 bytes. | |
32 | ||
33 | The second variant has the following entries in the pdata section. | |
34 | BeginAddress, PrologueLength (8 bits), EndAddress (22 bits), | |
35 | Use-32-bit-instruction (1 bit), and Exception-Handler-Exists (1 bit). | |
36 | If the FunctionLength is zero, or the Exception-Handler-Exists bit | |
37 | is true, a PDATA_EH block is placed directly before function entry. | |
38 | ||
39 | The third version has a function entry block of BeginAddress (RVA), | |
40 | EndAddress (RVA), and UnwindData (RVA). The description of the | |
33eaf5de | 41 | prologue, exception-handler, and additional SEH data is stored |
987499b2 KT |
42 | within the UNWIND_DATA field in the xdata section. |
43 | ||
44 | The pseudos: | |
45 | .seh_proc <fct_name> | |
46 | .seh_endprologue | |
681418c2 RH |
47 | .seh_handler <handler>[,@unwind][,@except] (x64) |
48 | .seh_handler <handler>[,<handler_data>] (others) | |
49 | .seh_handlerdata | |
987499b2 KT |
50 | .seh_eh |
51 | .seh_32/.seh_no32 | |
52 | .seh_endproc | |
53 | .seh_setframe <reg>,<offset> | |
54 | .seh_stackalloc | |
55 | .seh_pushreg | |
56 | .seh_savereg | |
987499b2 KT |
57 | .seh_savexmm |
58 | .seh_pushframe | |
3c6256d2 | 59 | .seh_code |
681418c2 | 60 | */ |
987499b2 KT |
61 | |
62 | /* architecture specific pdata/xdata handling. */ | |
63 | #define SEH_CMDS \ | |
64 | {"seh_proc", obj_coff_seh_proc, 0}, \ | |
65 | {"seh_endproc", obj_coff_seh_endproc, 0}, \ | |
681418c2 RH |
66 | {"seh_pushreg", obj_coff_seh_pushreg, 0}, \ |
67 | {"seh_savereg", obj_coff_seh_save, 1}, \ | |
987499b2 | 68 | {"seh_savexmm", obj_coff_seh_save, 2}, \ |
681418c2 | 69 | {"seh_pushframe", obj_coff_seh_pushframe, 0}, \ |
987499b2 KT |
70 | {"seh_endprologue", obj_coff_seh_endprologue, 0}, \ |
71 | {"seh_setframe", obj_coff_seh_setframe, 0}, \ | |
681418c2 | 72 | {"seh_stackalloc", obj_coff_seh_stackalloc, 0}, \ |
987499b2 KT |
73 | {"seh_eh", obj_coff_seh_eh, 0}, \ |
74 | {"seh_32", obj_coff_seh_32, 1}, \ | |
75 | {"seh_no32", obj_coff_seh_32, 0}, \ | |
681418c2 | 76 | {"seh_handler", obj_coff_seh_handler, 0}, \ |
3c6256d2 | 77 | {"seh_code", obj_coff_seh_code, 0}, \ |
681418c2 | 78 | {"seh_handlerdata", obj_coff_seh_handlerdata, 0}, |
987499b2 KT |
79 | |
80 | /* Type definitions. */ | |
81 | ||
82 | typedef struct seh_prologue_element | |
83 | { | |
681418c2 RH |
84 | int code; |
85 | int info; | |
86 | offsetT off; | |
987499b2 | 87 | symbolS *pc_addr; |
987499b2 KT |
88 | } seh_prologue_element; |
89 | ||
987499b2 KT |
90 | typedef struct seh_context |
91 | { | |
92 | struct seh_context *next; | |
681418c2 | 93 | |
2d7f4929 KT |
94 | /* Initial code-segment. */ |
95 | segT code_seg; | |
987499b2 KT |
96 | /* Function name. */ |
97 | char *func_name; | |
98 | /* BeginAddress. */ | |
987499b2 | 99 | symbolS *start_addr; |
987499b2 | 100 | /* EndAddress. */ |
987499b2 | 101 | symbolS *end_addr; |
681418c2 RH |
102 | /* Unwind data. */ |
103 | symbolS *xdata_addr; | |
987499b2 | 104 | /* PrologueEnd. */ |
987499b2 | 105 | symbolS *endprologue_addr; |
987499b2 | 106 | /* ExceptionHandler. */ |
681418c2 RH |
107 | expressionS handler; |
108 | /* ExceptionHandlerData. (arm, mips) */ | |
109 | expressionS handler_data; | |
110 | ||
111 | /* ARM .seh_eh directive seen. */ | |
987499b2 | 112 | int handler_written; |
681418c2 | 113 | |
987499b2 KT |
114 | /* WinCE specific data. */ |
115 | int use_instruction_32; | |
681418c2 RH |
116 | /* Was record already processed. */ |
117 | int done; | |
118 | ||
119 | /* x64 flags for the xdata header. */ | |
120 | int handler_flags; | |
121 | int subsection; | |
987499b2 | 122 | |
987499b2 KT |
123 | /* x64 framereg and frame offset information. */ |
124 | int framereg; | |
681418c2 RH |
125 | int frameoff; |
126 | ||
987499b2 | 127 | /* Information about x64 specific unwind data fields. */ |
681418c2 RH |
128 | int elems_count; |
129 | int elems_max; | |
987499b2 | 130 | seh_prologue_element *elems; |
987499b2 KT |
131 | } seh_context; |
132 | ||
133 | typedef enum seh_kind { | |
134 | seh_kind_unknown = 0, | |
135 | seh_kind_mips = 1, /* Used for MIPS and x86 pdata generation. */ | |
136 | seh_kind_arm = 2, /* Used for ARM, PPC, SH3, and SH4 pdata (PDATA_EH) generation. */ | |
137 | seh_kind_x64 = 3 /* Used for IA64 and x64 pdata/xdata generation. */ | |
138 | } seh_kind; | |
139 | ||
140 | /* Forward declarations. */ | |
681418c2 | 141 | static void obj_coff_seh_stackalloc (int); |
987499b2 KT |
142 | static void obj_coff_seh_setframe (int); |
143 | static void obj_coff_seh_endprologue (int); | |
681418c2 RH |
144 | static void obj_coff_seh_save (int); |
145 | static void obj_coff_seh_pushreg (int); | |
146 | static void obj_coff_seh_pushframe (int); | |
987499b2 KT |
147 | static void obj_coff_seh_endproc (int); |
148 | static void obj_coff_seh_eh (int); | |
149 | static void obj_coff_seh_32 (int); | |
150 | static void obj_coff_seh_proc (int); | |
151 | static void obj_coff_seh_handler (int); | |
681418c2 | 152 | static void obj_coff_seh_handlerdata (int); |
3c6256d2 | 153 | static void obj_coff_seh_code (int); |
987499b2 | 154 | |
45dfa85a | 155 | #define UNDSEC bfd_und_section_ptr |
284e0531 KT |
156 | |
157 | /* Check if x64 UNW_... macros are already defined. */ | |
158 | #ifndef PEX64_FLAG_NHANDLER | |
159 | /* We can't include here coff/pe.h header. So we have to copy macros | |
160 | from coff/pe.h here. */ | |
161 | #define PEX64_UNWCODE_CODE(VAL) ((VAL) & 0xf) | |
162 | #define PEX64_UNWCODE_INFO(VAL) (((VAL) >> 4) & 0xf) | |
163 | ||
164 | /* The unwind info. */ | |
165 | #define UNW_FLAG_NHANDLER 0 | |
166 | #define UNW_FLAG_EHANDLER 1 | |
167 | #define UNW_FLAG_UHANDLER 2 | |
168 | #define UNW_FLAG_FHANDLER 3 | |
169 | #define UNW_FLAG_CHAININFO 4 | |
170 | ||
171 | #define UNW_FLAG_MASK 0x1f | |
172 | ||
173 | /* The unwind codes. */ | |
174 | #define UWOP_PUSH_NONVOL 0 | |
175 | #define UWOP_ALLOC_LARGE 1 | |
176 | #define UWOP_ALLOC_SMALL 2 | |
177 | #define UWOP_SET_FPREG 3 | |
178 | #define UWOP_SAVE_NONVOL 4 | |
179 | #define UWOP_SAVE_NONVOL_FAR 5 | |
180 | #define UWOP_SAVE_XMM 6 | |
181 | #define UWOP_SAVE_XMM_FAR 7 | |
182 | #define UWOP_SAVE_XMM128 8 | |
183 | #define UWOP_SAVE_XMM128_FAR 9 | |
184 | #define UWOP_PUSH_MACHFRAME 10 | |
185 | ||
186 | #define PEX64_UWI_VERSION(VAL) ((VAL) & 7) | |
187 | #define PEX64_UWI_FLAGS(VAL) (((VAL) >> 3) & 0x1f) | |
188 | #define PEX64_UWI_FRAMEREG(VAL) ((VAL) & 0xf) | |
189 | #define PEX64_UWI_FRAMEOFF(VAL) (((VAL) >> 4) & 0xf) | |
190 | #define PEX64_UWI_SIZEOF_UWCODE_ARRAY(VAL) \ | |
191 | ((((VAL) + 1) & ~1) * 2) | |
192 | ||
193 | #define PEX64_OFFSET_TO_UNWIND_CODE 0x4 | |
194 | ||
195 | #define PEX64_OFFSET_TO_HANDLER_RVA (COUNTOFUNWINDCODES) \ | |
196 | (PEX64_OFFSET_TO_UNWIND_CODE + \ | |
197 | PEX64_UWI_SIZEOF_UWCODE_ARRAY(COUNTOFUNWINDCODES)) | |
198 | ||
199 | #define PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) \ | |
200 | (PEX64_OFFSET_TO_HANDLER_RVA(COUNTOFUNWINDCODES) + 4) | |
201 | ||
202 | #define PEX64_SCOPE_ENTRY(COUNTOFUNWINDCODES, IDX) \ | |
203 | (PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) + \ | |
204 | PEX64_SCOPE_ENTRY_SIZE * (IDX)) | |
205 | ||
206 | #endif |