Rev 5222 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5222 | serge | 1 | /* seh pdata/xdata coff object file format |
6324 | serge | 2 | Copyright (C) 2009-2015 Free Software Foundation, Inc. |
5222 | serge | 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 | |||
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 |
||
41 | prologue, excepetion-handler, and additional SEH data is stored |
||
42 | within the UNWIND_DATA field in the xdata section. |
||
43 | |||
44 | The pseudos: |
||
45 | .seh_proc |
||
46 | .seh_endprologue |
||
47 | .seh_handler |
||
48 | .seh_handler |
||
49 | .seh_handlerdata |
||
50 | .seh_eh |
||
51 | .seh_32/.seh_no32 |
||
52 | .seh_endproc |
||
53 | .seh_setframe |
||
54 | .seh_stackalloc |
||
55 | .seh_pushreg |
||
56 | .seh_savereg |
||
57 | .seh_savexmm |
||
58 | .seh_pushframe |
||
6324 | serge | 59 | .seh_code |
5222 | serge | 60 | */ |
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}, \ |
||
66 | {"seh_pushreg", obj_coff_seh_pushreg, 0}, \ |
||
67 | {"seh_savereg", obj_coff_seh_save, 1}, \ |
||
68 | {"seh_savexmm", obj_coff_seh_save, 2}, \ |
||
69 | {"seh_pushframe", obj_coff_seh_pushframe, 0}, \ |
||
70 | {"seh_endprologue", obj_coff_seh_endprologue, 0}, \ |
||
71 | {"seh_setframe", obj_coff_seh_setframe, 0}, \ |
||
72 | {"seh_stackalloc", obj_coff_seh_stackalloc, 0}, \ |
||
73 | {"seh_eh", obj_coff_seh_eh, 0}, \ |
||
74 | {"seh_32", obj_coff_seh_32, 1}, \ |
||
75 | {"seh_no32", obj_coff_seh_32, 0}, \ |
||
76 | {"seh_handler", obj_coff_seh_handler, 0}, \ |
||
6324 | serge | 77 | {"seh_code", obj_coff_seh_code, 0}, \ |
5222 | serge | 78 | {"seh_handlerdata", obj_coff_seh_handlerdata, 0}, |
79 | |||
80 | /* Type definitions. */ |
||
81 | |||
82 | typedef struct seh_prologue_element |
||
83 | { |
||
84 | int code; |
||
85 | int info; |
||
86 | offsetT off; |
||
87 | symbolS *pc_addr; |
||
88 | } seh_prologue_element; |
||
89 | |||
90 | typedef struct seh_context |
||
91 | { |
||
92 | struct seh_context *next; |
||
93 | |||
94 | /* Initial code-segment. */ |
||
95 | segT code_seg; |
||
96 | /* Function name. */ |
||
97 | char *func_name; |
||
98 | /* BeginAddress. */ |
||
99 | symbolS *start_addr; |
||
100 | /* EndAddress. */ |
||
101 | symbolS *end_addr; |
||
102 | /* Unwind data. */ |
||
103 | symbolS *xdata_addr; |
||
104 | /* PrologueEnd. */ |
||
105 | symbolS *endprologue_addr; |
||
106 | /* ExceptionHandler. */ |
||
107 | expressionS handler; |
||
108 | /* ExceptionHandlerData. (arm, mips) */ |
||
109 | expressionS handler_data; |
||
110 | |||
111 | /* ARM .seh_eh directive seen. */ |
||
112 | int handler_written; |
||
113 | |||
114 | /* WinCE specific data. */ |
||
115 | int use_instruction_32; |
||
116 | /* Was record already processed. */ |
||
117 | int done; |
||
118 | |||
119 | /* x64 flags for the xdata header. */ |
||
120 | int handler_flags; |
||
121 | int subsection; |
||
122 | |||
123 | /* x64 framereg and frame offset information. */ |
||
124 | int framereg; |
||
125 | int frameoff; |
||
126 | |||
127 | /* Information about x64 specific unwind data fields. */ |
||
128 | int elems_count; |
||
129 | int elems_max; |
||
130 | seh_prologue_element *elems; |
||
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. */ |
||
141 | static void obj_coff_seh_stackalloc (int); |
||
142 | static void obj_coff_seh_setframe (int); |
||
143 | static void obj_coff_seh_endprologue (int); |
||
144 | static void obj_coff_seh_save (int); |
||
145 | static void obj_coff_seh_pushreg (int); |
||
146 | static void obj_coff_seh_pushframe (int); |
||
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); |
||
152 | static void obj_coff_seh_handlerdata (int); |
||
6324 | serge | 153 | static void obj_coff_seh_code (int); |
5222 | serge | 154 | |
155 | #define UNDSEC bfd_und_section_ptr |
||
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 |