Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5222 | serge | 1 | /* seh pdata/xdata coff object file format |
2 | Copyright 2009, 2010, 2012 |
||
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 | |||
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 |
||
47 | .seh_endprologue |
||
48 | .seh_handler |
||
49 | .seh_handler |
||
50 | .seh_handlerdata |
||
51 | .seh_eh |
||
52 | .seh_32/.seh_no32 |
||
53 | .seh_endproc |
||
54 | .seh_setframe |
||
55 | .seh_stackalloc |
||
56 | .seh_pushreg |
||
57 | .seh_savereg |
||
58 | .seh_savexmm |
||
59 | .seh_pushframe |
||
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}, \ |
||
77 | {"seh_handlerdata", obj_coff_seh_handlerdata, 0}, |
||
78 | |||
79 | /* Type definitions. */ |
||
80 | |||
81 | typedef struct seh_prologue_element |
||
82 | { |
||
83 | int code; |
||
84 | int info; |
||
85 | offsetT off; |
||
86 | symbolS *pc_addr; |
||
87 | } seh_prologue_element; |
||
88 | |||
89 | typedef struct seh_context |
||
90 | { |
||
91 | struct seh_context *next; |
||
92 | |||
93 | /* Initial code-segment. */ |
||
94 | segT code_seg; |
||
95 | /* Function name. */ |
||
96 | char *func_name; |
||
97 | /* BeginAddress. */ |
||
98 | symbolS *start_addr; |
||
99 | /* EndAddress. */ |
||
100 | symbolS *end_addr; |
||
101 | /* Unwind data. */ |
||
102 | symbolS *xdata_addr; |
||
103 | /* PrologueEnd. */ |
||
104 | symbolS *endprologue_addr; |
||
105 | /* ExceptionHandler. */ |
||
106 | expressionS handler; |
||
107 | /* ExceptionHandlerData. (arm, mips) */ |
||
108 | expressionS handler_data; |
||
109 | |||
110 | /* ARM .seh_eh directive seen. */ |
||
111 | int handler_written; |
||
112 | |||
113 | /* WinCE specific data. */ |
||
114 | int use_instruction_32; |
||
115 | /* Was record already processed. */ |
||
116 | int done; |
||
117 | |||
118 | /* x64 flags for the xdata header. */ |
||
119 | int handler_flags; |
||
120 | int subsection; |
||
121 | |||
122 | /* x64 framereg and frame offset information. */ |
||
123 | int framereg; |
||
124 | int frameoff; |
||
125 | |||
126 | /* Information about x64 specific unwind data fields. */ |
||
127 | int elems_count; |
||
128 | int elems_max; |
||
129 | seh_prologue_element *elems; |
||
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. */ |
||
140 | static void obj_coff_seh_stackalloc (int); |
||
141 | static void obj_coff_seh_setframe (int); |
||
142 | static void obj_coff_seh_endprologue (int); |
||
143 | static void obj_coff_seh_save (int); |
||
144 | static void obj_coff_seh_pushreg (int); |
||
145 | static void obj_coff_seh_pushframe (int); |
||
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); |
||
151 | static void obj_coff_seh_handlerdata (int); |
||
152 | |||
153 | #define UNDSEC bfd_und_section_ptr |
||
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 |