1 /* seh pdata/xdata coff object file format
3 Free Software Foundation, Inc.
5 This file is part of GAS.
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)
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.
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
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.
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.
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.
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.
48 .seh_handler <handler>[,<handler-data>]]
52 .seh_setframe <reg>,<offset>
62 /* architecture specific pdata/xdata handling. */
64 {"seh_proc", obj_coff_seh_proc, 0}, \
65 {"seh_endproc", obj_coff_seh_endproc, 0}, \
66 {"seh_pushreg", obj_coff_seh_push, 0}, \
67 {"seh_savereg", obj_coff_seh_save, 0}, \
68 {"seh_savemm", obj_coff_seh_save, 1}, \
69 {"seh_savexmm", obj_coff_seh_save, 2}, \
70 {"seh_pushframe", obj_coff_seh_push, 1}, \
71 {"seh_endprologue", obj_coff_seh_endprologue, 0}, \
72 {"seh_setframe", obj_coff_seh_setframe, 0}, \
73 {"seh_stackalloc", obj_coff_seh_stack_alloc, 0}, \
74 {"seh_handler", obj_coff_seh_handler, 0}, \
75 {"seh_eh", obj_coff_seh_eh, 0}, \
76 {"seh_32", obj_coff_seh_32, 1}, \
77 {"seh_no32", obj_coff_seh_32, 0}, \
78 {"seh_scope", obj_coff_seh_scope, 0},
80 /* Type definitions. */
82 typedef struct seh_prologue_element
89 } seh_prologue_element
;
91 typedef struct seh_scope_elem
{
98 typedef struct seh_context
100 struct seh_context
*next
;
101 /* Was record alread processed. */
108 bfd_vma start_offset
;
114 char *endprologue_symbol
;
115 symbolS
*endprologue_addr
;
116 bfd_vma endprologue_offset
;
117 /* ExceptionHandler. */
119 /* ExceptionHandlerData. */
120 char *handler_data_name
;
122 /* WinCE specific data. */
123 int use_instruction_32
;
125 /* the bfd to store data within. */
127 /* the current section to generate data within. */
129 /* Relocations for section. */
130 unsigned int count_reloc
;
131 /* Symbols within section. */
132 unsigned int count_syms
;
133 /* Iterator for text lable generation. */
134 unsigned int tlbl_count
;
135 /* Iterator for xdata lable generation. */
136 unsigned int xlbl_count
;
137 /* The name of the first xdata label. */
139 /* FIelds used for x64 generation of chained information. */
142 int *xdata_elm_start
;
143 /* Size and offset within current generated xdata section. */
146 /* x64 framereg and frame offset information. */
149 /* Information about x64 specific unwind data fields. */
152 seh_prologue_element
*elems
;
155 seh_scope_elem
*scopes
;
158 typedef enum seh_kind
{
159 seh_kind_unknown
= 0,
160 seh_kind_mips
= 1, /* Used for MIPS and x86 pdata generation. */
161 seh_kind_arm
= 2, /* Used for ARM, PPC, SH3, and SH4 pdata (PDATA_EH) generation. */
162 seh_kind_x64
= 3 /* Used for IA64 and x64 pdata/xdata generation. */
165 /* Forward declarations. */
166 static void obj_coff_seh_stack_alloc (int);
167 static void obj_coff_seh_setframe (int);
168 static void obj_coff_seh_endprologue (int);
169 static void obj_coff_seh_save (int);
170 static void obj_coff_seh_push (int);
171 static void obj_coff_seh_endproc (int);
172 static void obj_coff_seh_eh (int);
173 static void obj_coff_seh_32 (int);
174 static void obj_coff_seh_proc (int);
175 static void obj_coff_seh_handler (int);
176 static void obj_coff_seh_scope (int);
177 static int seh_read_offset (const char *, bfd_vma
*);
178 static int seh_x64_read_reg (const char *, int, int *);
179 static void seh_x64_make_prologue_element (int, int, bfd_vma
);
180 static void make_function_entry_pdata (seh_context
*c
);
182 #define UNDSEC (asection *) &bfd_und_section
184 /* Check if x64 UNW_... macros are already defined. */
185 #ifndef PEX64_FLAG_NHANDLER
186 /* We can't include here coff/pe.h header. So we have to copy macros
187 from coff/pe.h here. */
188 #define PEX64_UNWCODE_CODE(VAL) ((VAL) & 0xf)
189 #define PEX64_UNWCODE_INFO(VAL) (((VAL) >> 4) & 0xf)
191 /* The unwind info. */
192 #define UNW_FLAG_NHANDLER 0
193 #define UNW_FLAG_EHANDLER 1
194 #define UNW_FLAG_UHANDLER 2
195 #define UNW_FLAG_FHANDLER 3
196 #define UNW_FLAG_CHAININFO 4
198 #define UNW_FLAG_MASK 0x1f
200 /* The unwind codes. */
201 #define UWOP_PUSH_NONVOL 0
202 #define UWOP_ALLOC_LARGE 1
203 #define UWOP_ALLOC_SMALL 2
204 #define UWOP_SET_FPREG 3
205 #define UWOP_SAVE_NONVOL 4
206 #define UWOP_SAVE_NONVOL_FAR 5
207 #define UWOP_SAVE_XMM 6
208 #define UWOP_SAVE_XMM_FAR 7
209 #define UWOP_SAVE_XMM128 8
210 #define UWOP_SAVE_XMM128_FAR 9
211 #define UWOP_PUSH_MACHFRAME 10
213 #define PEX64_UWI_VERSION(VAL) ((VAL) & 7)
214 #define PEX64_UWI_FLAGS(VAL) (((VAL) >> 3) & 0x1f)
215 #define PEX64_UWI_FRAMEREG(VAL) ((VAL) & 0xf)
216 #define PEX64_UWI_FRAMEOFF(VAL) (((VAL) >> 4) & 0xf)
217 #define PEX64_UWI_SIZEOF_UWCODE_ARRAY(VAL) \
218 ((((VAL) + 1) & ~1) * 2)
220 #define PEX64_OFFSET_TO_UNWIND_CODE 0x4
222 #define PEX64_OFFSET_TO_HANDLER_RVA (COUNTOFUNWINDCODES) \
223 (PEX64_OFFSET_TO_UNWIND_CODE + \
224 PEX64_UWI_SIZEOF_UWCODE_ARRAY(COUNTOFUNWINDCODES))
226 #define PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) \
227 (PEX64_OFFSET_TO_HANDLER_RVA(COUNTOFUNWINDCODES) + 4)
229 #define PEX64_SCOPE_ENTRY(COUNTOFUNWINDCODES, IDX) \
230 (PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) + \
231 PEX64_SCOPE_ENTRY_SIZE * (IDX))