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