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