Home | History | Annotate | Line # | Download | only in ia64
      1  1.1.1.11  mrg /* Copyright (C) 2004-2024 Free Software Foundation, Inc.
      2       1.1  mrg    Contributed by Douglas B Rupp <rupp (at) gnat.com>
      3       1.1  mrg 
      4       1.1  mrg    This file is part of GCC.
      5       1.1  mrg 
      6       1.1  mrg    GCC is free software; you can redistribute it and/or modify
      7       1.1  mrg    it under the terms of the GNU General Public License as published by
      8       1.1  mrg    the Free Software Foundation; either version 3, or (at your option)
      9       1.1  mrg    any later version.
     10       1.1  mrg 
     11       1.1  mrg    GCC is distributed in the hope that it will be useful,
     12       1.1  mrg    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13       1.1  mrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14       1.1  mrg    GNU General Public License for more details.
     15       1.1  mrg 
     16       1.1  mrg    Under Section 7 of GPL version 3, you are granted additional
     17       1.1  mrg    permissions described in the GCC Runtime Library Exception, version
     18       1.1  mrg    3.1, as published by the Free Software Foundation.
     19       1.1  mrg 
     20       1.1  mrg    You should have received a copy of the GNU General Public License and
     21       1.1  mrg    a copy of the GCC Runtime Library Exception along with this program;
     22       1.1  mrg    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23       1.1  mrg    <http://www.gnu.org/licenses/>.  */
     24       1.1  mrg 
     25       1.1  mrg /* Locate the FDE entry for a given address, using VMS Starlet routines
     26       1.1  mrg    to avoid register/deregister calls at DSO load/unload.  */
     27       1.1  mrg 
     28       1.1  mrg #include "tconfig.h"
     29       1.1  mrg #include "tsystem.h"
     30       1.1  mrg #include "coretypes.h"
     31       1.1  mrg #include "tm.h"
     32       1.1  mrg #include "libgcc_tm.h"
     33       1.1  mrg #include <stddef.h>
     34       1.1  mrg #include <stdlib.h>
     35       1.1  mrg #include <stdio.h>
     36       1.1  mrg #include "unwind-ia64.h"
     37       1.1  mrg 
     38       1.1  mrg #include <ossddef.h>
     39       1.1  mrg #ifndef SS$_NORMAL
     40       1.1  mrg #define SS$_NORMAL 1
     41       1.1  mrg #endif
     42       1.1  mrg 
     43       1.1  mrg #define UNW_IVMS_MODE(HEADER) (((HEADER) >> 44) & 0x3L)
     44       1.1  mrg 
     45       1.1  mrg typedef struct
     46       1.1  mrg {
     47       1.1  mrg   unw_word start_offset;
     48       1.1  mrg   unw_word end_offset;
     49       1.1  mrg   unw_word info_offset;
     50       1.1  mrg   unw_word gp_value;
     51       1.1  mrg }  vms_unw_table_entry;
     52       1.1  mrg 
     53       1.1  mrg typedef unsigned long long uqword;
     54       1.1  mrg 
     55       1.1  mrg /* ENTRY is the unwind table entry found for a PC part of call chain we're
     56       1.1  mrg    unwinding through.  Return whether we should force the generic unwinder
     57       1.1  mrg    to resort to "fallback" processing.  */
     58       1.1  mrg 
     59       1.1  mrg static int
     60       1.1  mrg force_fallback_processing_for (void * pc, vms_unw_table_entry * entry)
     61       1.1  mrg {
     62       1.1  mrg   static int eh_debug = -1;
     63       1.1  mrg 
     64       1.1  mrg   uqword * unw_info_block = (uqword *)entry->info_offset;
     65       1.1  mrg   uqword header = *unw_info_block;
     66       1.1  mrg 
     67       1.1  mrg   /* We need to force fallback processing in two cases:
     68       1.1  mrg 
     69       1.1  mrg      1/ The exception dispatch frame, since only our fallback
     70       1.1  mrg         processing knows how to properly unwind through it, and
     71       1.1  mrg 
     72       1.1  mrg      2/ A bottom of stack frame, since only our fallback processing
     73       1.1  mrg         will ensure we don't try to unwind further past it, which
     74       1.1  mrg         would get us into unknown territory and likely cause a severe
     75       1.1  mrg         crash along the way.
     76       1.1  mrg 
     77       1.1  mrg      The two cases are indicated by non-default values for specific
     78       1.1  mrg      bits in the OS Specific Data (OSSD) General Information block
     79       1.1  mrg      associated with such frames.  */
     80       1.1  mrg 
     81       1.1  mrg   ossddef * ossd;
     82       1.1  mrg 
     83       1.1  mrg   if (eh_debug == -1)
     84       1.1  mrg     {
     85       1.1  mrg       char * EH_DEBUG = getenv ("EH_DEBUG");
     86       1.1  mrg       eh_debug = EH_DEBUG ? atoi (EH_DEBUG) : 0;
     87       1.1  mrg     }
     88       1.1  mrg 
     89       1.1  mrg   if (eh_debug)
     90       1.1  mrg     {
     91       1.1  mrg       printf ("pc @ 0x%p, block @ 0x%p, header = 0x%016llx\n",
     92       1.1  mrg 	      pc, unw_info_block, header);
     93       1.1  mrg       printf ("mode = %d, length = %ld, handler = %d\n",
     94       1.1  mrg 	      (int)UNW_IVMS_MODE (header), UNW_LENGTH (header),
     95       1.1  mrg 	      UNW_FLAG_EHANDLER (header) || UNW_FLAG_EHANDLER (header));
     96       1.1  mrg     }
     97       1.1  mrg 
     98       1.1  mrg   /* An OSSD block is there for IVMS_MODE == 3 only.  */
     99       1.1  mrg   if (UNW_IVMS_MODE (header) != 3)
    100       1.1  mrg     return 0;
    101       1.1  mrg 
    102       1.1  mrg   /* The OSSD block is found past the header, unwind descriptor area
    103       1.1  mrg      and condition handler pointer, if any.  */
    104       1.1  mrg   ossd = (ossddef *)
    105       1.1  mrg     /* Beware: uqword pointer arithmetic below.  */
    106       1.1  mrg     (unw_info_block
    107       1.1  mrg      + 1
    108       1.1  mrg      + UNW_LENGTH (header)
    109       1.1  mrg      + (UNW_FLAG_EHANDLER (header) || UNW_FLAG_EHANDLER (header)));
    110       1.1  mrg 
    111       1.1  mrg   /* "A General Information segment may be omitted if all of its fields
    112       1.1  mrg       would have their default values.  If a General Information segment
    113       1.1  mrg       is present, it must be the first in the OSSD area."  So ...  */
    114       1.1  mrg 
    115       1.1  mrg   if (eh_debug)
    116       1.1  mrg     printf ("ossd @ 0x%p\n", ossd);
    117       1.1  mrg 
    118       1.1  mrg   if (eh_debug && ossd->ossd$v_type == OSSD$K_GENERAL_INFO)
    119       1.1  mrg     printf ("exc_frame = %d - bot_frame = %d - base_frame = %d\n",
    120       1.1  mrg 	    ossd->ossd$v_exception_frame,
    121       1.1  mrg 	    ossd->ossd$v_bottom_of_stack,
    122       1.1  mrg 	    ossd->ossd$v_base_frame);
    123       1.1  mrg 
    124       1.1  mrg   return
    125       1.1  mrg     ossd->ossd$v_type == OSSD$K_GENERAL_INFO
    126       1.1  mrg     && (ossd->ossd$v_exception_frame
    127       1.1  mrg 	|| ossd->ossd$v_bottom_of_stack || ossd->ossd$v_base_frame);
    128       1.1  mrg }
    129       1.1  mrg 
    130       1.1  mrg /* Return a pointer to the unwind table entry for the function
    131       1.1  mrg    containing PC, 0 if we cannot find an entry or if the one we find
    132       1.1  mrg    calls for fallback processing.  */
    133       1.1  mrg 
    134       1.1  mrg struct unw_table_entry *
    135       1.1  mrg _Unwind_FindTableEntry (void *pc, unw_word *segment_base,
    136       1.1  mrg                         unw_word *gp, struct unw_table_entry *ent)
    137       1.1  mrg {
    138       1.1  mrg   vms_unw_table_entry vueblock;
    139       1.1  mrg 
    140       1.1  mrg   if (SYS$GET_UNWIND_ENTRY_INFO (pc, &vueblock, 0) != SS$_NORMAL)
    141       1.1  mrg     return 0;
    142       1.1  mrg 
    143       1.1  mrg   /* If there is no unwind information, use fallback.  */
    144       1.1  mrg   if (vueblock.info_offset == 0)
    145       1.1  mrg     return 0;
    146       1.1  mrg 
    147       1.1  mrg   /* If we need to force fallback processing, just pretend there is
    148       1.1  mrg      no entry.  */
    149       1.1  mrg   if (force_fallback_processing_for (pc, &vueblock))
    150       1.1  mrg     return 0;
    151       1.1  mrg 
    152       1.1  mrg   *segment_base = 0; /* ??? Fixme. ??? */
    153       1.1  mrg   *gp = vueblock.gp_value;
    154       1.1  mrg   ent->start_offset = vueblock.start_offset;
    155       1.1  mrg   ent->end_offset = vueblock.end_offset;
    156       1.1  mrg   ent->info_offset = vueblock.info_offset;
    157       1.1  mrg 
    158       1.1  mrg   return ent;
    159       1.1  mrg }
    160