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
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
48  .seh_handler <handler>[,@unwind][,@except]	(x64)
49  .seh_handler <handler>[,<handler_data>]	(others)
50  .seh_handlerdata
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
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
81typedef struct seh_prologue_element
82{
83  int code;
84  int info;
85  offsetT off;
86  symbolS *pc_addr;
87} seh_prologue_element;
88
89typedef 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
132typedef 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.  */
140static void obj_coff_seh_stackalloc (int);
141static void obj_coff_seh_setframe (int);
142static void obj_coff_seh_endprologue (int);
143static void obj_coff_seh_save (int);
144static void obj_coff_seh_pushreg (int);
145static void obj_coff_seh_pushframe (int);
146static void obj_coff_seh_endproc  (int);
147static void obj_coff_seh_eh (int);
148static void obj_coff_seh_32 (int);
149static void obj_coff_seh_proc  (int);
150static void obj_coff_seh_handler (int);
151static void obj_coff_seh_handlerdata (int);
152
153#define UNDSEC (asection *) &bfd_und_section
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
206