1/* scfidw2gen.c - Support for emission of synthesized Dwarf2 CFI. 2 Copyright (C) 2023 Free Software Foundation, Inc. 3 4 This file is part of GAS, the GNU Assembler. 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#include "as.h" 22#include "ginsn.h" 23#include "scfi.h" 24#include "dw2gencfi.h" 25#include "subsegs.h" 26#include "scfidw2gen.h" 27 28#if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN) 29 30static bool scfi_ignore_warn_once; 31 32static void 33dot_scfi_ignore (int ignored ATTRIBUTE_UNUSED) 34{ 35 gas_assert (flag_synth_cfi); 36 37 if (!scfi_ignore_warn_once) 38 { 39 as_warn (_("SCFI ignores most user-specified CFI directives")); 40 scfi_ignore_warn_once = true; 41 } 42 ignore_rest_of_line (); 43} 44 45static void 46scfi_process_cfi_label (void) 47{ 48 char *name; 49 ginsnS *ginsn; 50 51 name = read_symbol_name (); 52 if (name == NULL) 53 return; 54 55 /* Add a new ginsn. */ 56 ginsn = ginsn_new_phantom (symbol_temp_new_now ()); 57 frch_ginsn_data_append (ginsn); 58 59 scfi_op_add_cfi_label (ginsn, name); 60 /* TODO. */ 61 // free (name); 62 63 demand_empty_rest_of_line (); 64} 65 66static void 67scfi_process_cfi_signal_frame (void) 68{ 69 ginsnS *ginsn; 70 71 ginsn = ginsn_new_phantom (symbol_temp_new_now ()); 72 frch_ginsn_data_append (ginsn); 73 74 scfi_op_add_signal_frame (ginsn); 75} 76 77static void 78dot_scfi (int arg) 79{ 80 switch (arg) 81 { 82 case CFI_label: 83 scfi_process_cfi_label (); 84 break; 85 case CFI_signal_frame: 86 scfi_process_cfi_signal_frame (); 87 break; 88 default: 89 abort (); 90 } 91} 92 93const pseudo_typeS scfi_pseudo_table[] = 94 { 95 { "cfi_sections", dot_cfi_sections, 0 }, /* No ignore. */ 96 { "cfi_signal_frame", dot_scfi, CFI_signal_frame }, /* No ignore. */ 97 { "cfi_label", dot_scfi, CFI_label }, /* No ignore. */ 98 { "cfi_startproc", dot_scfi_ignore, 0 }, 99 { "cfi_endproc", dot_scfi_ignore, 0 }, 100 { "cfi_fde_data", dot_scfi_ignore, 0 }, 101 { "cfi_def_cfa", dot_scfi_ignore, 0 }, 102 { "cfi_def_cfa_register", dot_scfi_ignore, 0 }, 103 { "cfi_def_cfa_offset", dot_scfi_ignore, 0 }, 104 { "cfi_adjust_cfa_offset", dot_scfi_ignore, 0 }, 105 { "cfi_offset", dot_scfi_ignore, 0 }, 106 { "cfi_rel_offset", dot_scfi_ignore, 0 }, 107 { "cfi_register", dot_scfi_ignore, 0 }, 108 { "cfi_return_column", dot_scfi_ignore, 0 }, 109 { "cfi_restore", dot_scfi_ignore, 0 }, 110 { "cfi_undefined", dot_scfi_ignore, 0 }, 111 { "cfi_same_value", dot_scfi_ignore, 0 }, 112 { "cfi_remember_state", dot_scfi_ignore, 0 }, 113 { "cfi_restore_state", dot_scfi_ignore, 0 }, 114 { "cfi_window_save", dot_scfi_ignore, 0 }, 115 { "cfi_negate_ra_state", dot_scfi_ignore, 0 }, 116 { "cfi_escape", dot_scfi_ignore, 0 }, 117 { "cfi_personality", dot_scfi_ignore, 0 }, 118 { "cfi_personality_id", dot_scfi_ignore, 0 }, 119 { "cfi_lsda", dot_scfi_ignore, 0 }, 120 { "cfi_val_encoded_addr", dot_scfi_ignore, 0 }, 121 { "cfi_inline_lsda", dot_scfi_ignore, 0 }, 122 { "cfi_val_offset", dot_scfi_ignore, 0 }, 123 { NULL, NULL, 0 } 124 }; 125 126void 127scfi_dot_cfi_startproc (const symbolS *start_sym) 128{ 129 if (frchain_now->frch_cfi_data != NULL) 130 { 131 as_bad (_("SCFI: missing previous SCFI endproc marker")); 132 return; 133 } 134 135 cfi_new_fde ((symbolS *)start_sym); 136 137 cfi_set_sections (); 138 139 frchain_now->frch_cfi_data->cur_cfa_offset = 0; 140 141 /* By default, SCFI machinery assumes .cfi_startproc is used without 142 parameter simple. */ 143 tc_cfi_frame_initial_instructions (); 144 145 if ((all_cfi_sections & CFI_EMIT_target) != 0) 146 tc_cfi_startproc (); 147} 148 149void 150scfi_dot_cfi_endproc (const symbolS *end_sym) 151{ 152 struct fde_entry *fde_last; 153 154 if (frchain_now->frch_cfi_data == NULL) 155 { 156 as_bad (_(".cfi_endproc without corresponding .cfi_startproc")); 157 return; 158 } 159 160 fde_last = frchain_now->frch_cfi_data->cur_fde_data; 161 cfi_set_last_fde (fde_last); 162 163 cfi_end_fde ((symbolS *)end_sym); 164 165 if ((all_cfi_sections & CFI_EMIT_target) != 0) 166 tc_cfi_endproc (fde_last); 167} 168 169void 170scfi_dot_cfi (int arg, unsigned reg1, unsigned reg2, offsetT offset, 171 const char *name, const symbolS *advloc) 172{ 173 if (frchain_now->frch_cfi_data == NULL) 174 { 175 as_bad (_("CFI instruction used without previous .cfi_startproc")); 176 return; 177 } 178 179 /* If the last address was not at the current PC, advance to current. */ 180 if (frchain_now->frch_cfi_data->last_address != advloc) 181 cfi_add_advance_loc ((symbolS *)advloc); 182 183 switch (arg) 184 { 185 case DW_CFA_offset: 186 cfi_add_CFA_offset (reg1, offset); 187 break; 188 189 case DW_CFA_val_offset: 190 cfi_add_CFA_val_offset (reg1, offset); 191 break; 192 193 case CFI_rel_offset: 194 cfi_add_CFA_offset (reg1, 195 offset - frchain_now->frch_cfi_data->cur_cfa_offset); 196 break; 197 198 case DW_CFA_def_cfa: 199 cfi_add_CFA_def_cfa (reg1, offset); 200 break; 201 202 case DW_CFA_register: 203 cfi_add_CFA_register (reg1, reg2); 204 break; 205 206 case DW_CFA_def_cfa_register: 207 cfi_add_CFA_def_cfa_register (reg1); 208 break; 209 210 case DW_CFA_def_cfa_offset: 211 cfi_add_CFA_def_cfa_offset (offset); 212 break; 213 214 case CFI_adjust_cfa_offset: 215 cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset 216 + offset); 217 break; 218 219 case DW_CFA_restore: 220 cfi_add_CFA_restore (reg1); 221 break; 222 223 case DW_CFA_remember_state: 224 cfi_add_CFA_remember_state (); 225 break; 226 227 case DW_CFA_restore_state: 228 cfi_add_CFA_restore_state (); 229 break; 230 231 case CFI_label: 232 cfi_add_label (name); 233 break; 234 235 case CFI_signal_frame: 236 frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1; 237 break; 238 239/* 240 case DW_CFA_undefined: 241 for (;;) 242 { 243 reg1 = cfi_parse_reg (); 244 cfi_add_CFA_undefined (reg1); 245 SKIP_WHITESPACE (); 246 if (*input_line_pointer != ',') 247 break; 248 ++input_line_pointer; 249 } 250 break; 251 252 case DW_CFA_same_value: 253 reg1 = cfi_parse_reg (); 254 cfi_add_CFA_same_value (reg1); 255 break; 256 257 case CFI_return_column: 258 reg1 = cfi_parse_reg (); 259 cfi_set_return_column (reg1); 260 break; 261 262 case DW_CFA_GNU_window_save: 263 cfi_add_CFA_insn (DW_CFA_GNU_window_save); 264 break; 265 266*/ 267 default: 268 abort (); 269 } 270} 271 272#endif 273