1  /* seh pdata/xdata coff object file format
       2     Copyright (C) 2009-2023 Free Software Foundation, Inc.
       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, exception-handler, and additional SEH data is stored
      42    within the UNWIND_DATA field in the xdata section.
      43  
      44    The pseudos:
      45    .seh_proc <fct_name>
      46    .seh_endprologue
      47    .seh_handler <handler>[,@unwind][,@except]	(x64)
      48    .seh_handler <handler>[,<handler_data>]	(others)
      49    .seh_handlerdata
      50    .seh_eh
      51    .seh_32/.seh_no32
      52    .seh_endproc
      53    .seh_setframe <reg>,<offset>
      54    .seh_stackalloc
      55    .seh_pushreg
      56    .seh_savereg
      57    .seh_savexmm
      58    .seh_pushframe
      59    .seh_code
      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_code", obj_coff_seh_code, 0}, \
      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);
     153  static void obj_coff_seh_code (int);
     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