]> oss.titaniummirror.com Git - msp430-binutils.git/blobdiff - gas/config/obj-coff-seh.h
Merge commit 'upstream/2.20'
[msp430-binutils.git] / gas / config / obj-coff-seh.h
diff --git a/gas/config/obj-coff-seh.h b/gas/config/obj-coff-seh.h
new file mode 100644 (file)
index 0000000..aa151cd
--- /dev/null
@@ -0,0 +1,234 @@
+/* seh pdata/xdata coff object file format
+   Copyright 2009
+   Free Software Foundation, Inc.
+
+   This file is part of GAS.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* Short overview:
+  There are at the moment three different function entry formats preset.
+  The first is the MIPS one. The second version
+  is for ARM, PPC, SH3, and SH4 mainly for Windows CE.
+  The third is the IA64 and x64 version. Note, the IA64 isn't implemented yet,
+  but to find information about it, please see specification about IA64 on
+  http://download.intel.com/design/Itanium/Downloads/245358.pdf file.
+
+  The first version has just entries in the pdata section: BeginAddress,
+  EndAddress, ExceptionHandler, HandlerData, and PrologueEndAddress. Each
+  value is a pointer to the corresponding data and has size of 4 bytes.
+
+  The second variant has the following entries in the pdata section.
+  BeginAddress, PrologueLength (8 bits), EndAddress (22 bits),
+  Use-32-bit-instruction (1 bit), and Exception-Handler-Exists (1 bit).
+  If the FunctionLength is zero, or the Exception-Handler-Exists bit
+  is true, a PDATA_EH block is placed directly before function entry.
+
+  The third version has a function entry block of BeginAddress (RVA),
+  EndAddress (RVA), and UnwindData (RVA). The description of the
+  prologue, excepetion-handler, and additional SEH data is stored
+  within the UNWIND_DATA field in the xdata section.
+
+  The pseudos:
+  .seh_proc <fct_name>
+  .seh_endprologue
+  .seh_handler <handler>[,<handler-data>]]
+  .seh_eh
+  .seh_32/.seh_no32
+  .seh_endproc
+  .seh_setframe <reg>,<offset>
+  .seh_stackalloc
+  .seh_pushreg
+  .seh_savereg
+  .seh_savemm
+  .seh_savexmm
+  .seh_pushframe
+  .seh_scope
+  */
+
+/* architecture specific pdata/xdata handling.  */
+#define SEH_CMDS \
+        {"seh_proc", obj_coff_seh_proc, 0}, \
+        {"seh_endproc", obj_coff_seh_endproc, 0}, \
+        {"seh_pushreg", obj_coff_seh_push, 0}, \
+        {"seh_savereg", obj_coff_seh_save, 0}, \
+        {"seh_savemm", obj_coff_seh_save, 1}, \
+        {"seh_savexmm", obj_coff_seh_save, 2}, \
+        {"seh_pushframe", obj_coff_seh_push, 1}, \
+        {"seh_endprologue", obj_coff_seh_endprologue, 0}, \
+        {"seh_setframe", obj_coff_seh_setframe, 0}, \
+        {"seh_stackalloc", obj_coff_seh_stack_alloc, 0}, \
+       {"seh_handler", obj_coff_seh_handler, 0}, \
+       {"seh_eh", obj_coff_seh_eh, 0}, \
+       {"seh_32", obj_coff_seh_32, 1}, \
+       {"seh_no32", obj_coff_seh_32, 0}, \
+       {"seh_scope", obj_coff_seh_scope, 0},
+
+/* Type definitions.  */
+
+typedef struct seh_prologue_element
+{
+  symbolS *pc_addr;
+  char *pc_symbol;
+  int kind;
+  int reg;
+  bfd_vma offset;
+} seh_prologue_element;
+
+typedef struct seh_scope_elem {
+  char *begin_addr;
+  char *end_addr;
+  char *handler_addr;
+  char *jump_addr;
+} seh_scope_elem;
+
+typedef struct seh_context
+{
+  struct seh_context *next;
+  /* Was record alread processed.  */
+  int done;
+  /* Function name.  */
+  char *func_name;
+  /* BeginAddress.  */
+  char *start_symbol;
+  symbolS *start_addr;
+  bfd_vma start_offset;
+  /* EndAddress.  */
+  char *end_symbol;
+  symbolS *end_addr;
+  bfd_vma end_offset;
+  /* PrologueEnd.  */
+  char *endprologue_symbol;
+  symbolS *endprologue_addr;
+  bfd_vma endprologue_offset;
+  /* ExceptionHandler.  */
+  char *handler_name;
+  /* ExceptionHandlerData.  */
+  char *handler_data_name;
+  int handler_written;
+  /* WinCE specific data.  */
+  int use_instruction_32;
+
+  /* the bfd to store data within.  */
+  bfd *abfd;
+  /* the current section to generate data within.  */
+  asection *section;
+  /* Relocations for section.  */
+  unsigned int count_reloc;
+  /* Symbols within section.  */
+  unsigned int count_syms;
+  /* Iterator for text lable generation.  */
+  unsigned int tlbl_count;
+  /* Iterator for xdata lable generation.  */
+  unsigned int xlbl_count;
+  /* The name of the first xdata label.  */
+  char *xdata_first;
+  /* FIelds used for x64 generation of chained information.  */
+  char **xdata_names;
+  char **xdata_pcsyms;
+  int *xdata_elm_start;
+  /* Size and offset within current generated xdata section.  */
+  size_t xdata_sz;
+  size_t xdata_offset;
+  /* x64 framereg and frame offset information.  */
+  int framereg;
+  bfd_vma frameoff;
+  /* Information about x64 specific unwind data fields.  */
+  size_t elems_count;
+  size_t elems_max;
+  seh_prologue_element *elems;
+  size_t scope_max;
+  size_t scope_count;
+  seh_scope_elem *scopes;
+} seh_context;
+
+typedef enum seh_kind {
+  seh_kind_unknown = 0,
+  seh_kind_mips = 1,  /* Used for MIPS and x86 pdata generation.  */
+  seh_kind_arm = 2,   /* Used for ARM, PPC, SH3, and SH4 pdata (PDATA_EH) generation.  */
+  seh_kind_x64 = 3    /* Used for IA64 and x64 pdata/xdata generation.  */
+} seh_kind;
+
+/* Forward declarations.  */
+static void obj_coff_seh_stack_alloc (int);
+static void obj_coff_seh_setframe (int);
+static void obj_coff_seh_endprologue (int);
+static void obj_coff_seh_save  (int);
+static void obj_coff_seh_push  (int);
+static void obj_coff_seh_endproc  (int);
+static void obj_coff_seh_eh (int);
+static void obj_coff_seh_32 (int);
+static void obj_coff_seh_proc  (int);
+static void obj_coff_seh_handler (int);
+static void obj_coff_seh_scope (int);
+static int seh_read_offset (const char *, bfd_vma *);
+static int seh_x64_read_reg (const char *, int, int *);
+static void seh_x64_make_prologue_element (int, int, bfd_vma);
+static void make_function_entry_pdata (seh_context *c);
+
+#define UNDSEC (asection *) &bfd_und_section
+
+/* Check if x64 UNW_... macros are already defined.  */
+#ifndef PEX64_FLAG_NHANDLER
+/* We can't include here coff/pe.h header. So we have to copy macros
+   from coff/pe.h here.  */
+#define PEX64_UNWCODE_CODE(VAL) ((VAL) & 0xf)
+#define PEX64_UNWCODE_INFO(VAL) (((VAL) >> 4) & 0xf)
+
+/* The unwind info.  */
+#define UNW_FLAG_NHANDLER     0
+#define UNW_FLAG_EHANDLER     1
+#define UNW_FLAG_UHANDLER     2
+#define UNW_FLAG_FHANDLER     3
+#define UNW_FLAG_CHAININFO    4
+
+#define UNW_FLAG_MASK         0x1f
+
+/* The unwind codes.  */
+#define UWOP_PUSH_NONVOL      0
+#define UWOP_ALLOC_LARGE      1
+#define UWOP_ALLOC_SMALL      2
+#define UWOP_SET_FPREG        3
+#define UWOP_SAVE_NONVOL      4
+#define UWOP_SAVE_NONVOL_FAR  5
+#define UWOP_SAVE_XMM         6
+#define UWOP_SAVE_XMM_FAR     7
+#define UWOP_SAVE_XMM128      8
+#define UWOP_SAVE_XMM128_FAR  9
+#define UWOP_PUSH_MACHFRAME   10
+
+#define PEX64_UWI_VERSION(VAL)  ((VAL) & 7)
+#define PEX64_UWI_FLAGS(VAL)    (((VAL) >> 3) & 0x1f)
+#define PEX64_UWI_FRAMEREG(VAL) ((VAL) & 0xf)
+#define PEX64_UWI_FRAMEOFF(VAL) (((VAL) >> 4) & 0xf)
+#define PEX64_UWI_SIZEOF_UWCODE_ARRAY(VAL) \
+  ((((VAL) + 1) & ~1) * 2)
+
+#define PEX64_OFFSET_TO_UNWIND_CODE 0x4
+
+#define PEX64_OFFSET_TO_HANDLER_RVA (COUNTOFUNWINDCODES) \
+  (PEX64_OFFSET_TO_UNWIND_CODE + \
+   PEX64_UWI_SIZEOF_UWCODE_ARRAY(COUNTOFUNWINDCODES))
+
+#define PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) \
+  (PEX64_OFFSET_TO_HANDLER_RVA(COUNTOFUNWINDCODES) + 4)
+
+#define PEX64_SCOPE_ENTRY(COUNTOFUNWINDCODES, IDX) \
+  (PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) + \
+   PEX64_SCOPE_ENTRY_SIZE * (IDX))
+
+#endif
+