static void output_fde (struct fde_entry *fde, struct cie_entry *cie, struct cfi_insn_data *first, int align) { symbolS *after_size_address, *end_address; expressionS exp; after_size_address = symbol_temp_make (); end_address = symbol_temp_make (); exp.X_op = O_subtract; exp.X_add_symbol = end_address; exp.X_op_symbol = after_size_address; exp.X_add_number = 0; emit_expr (&exp, 4); /* Length. */ symbol_set_value_now (after_size_address); exp.X_add_symbol = after_size_address; exp.X_op_symbol = cie->start_address; emit_expr (&exp, 4); /* CIE offset. */ #ifdef DIFF_EXPR_OK exp.X_add_symbol = fde->start_address; exp.X_op_symbol = symbol_temp_new_now (); emit_expr (&exp, 4); /* Code offset. */ #else exp.X_op = O_symbol; exp.X_add_symbol = fde->start_address; exp.X_op_symbol = NULL; #ifdef tc_cfi_emit_pcrel_expr tc_cfi_emit_pcrel_expr (&exp, 4); /* Code offset. */ #else emit_expr (&exp, 4); /* Code offset. */ #endif exp.X_op = O_subtract; #endif exp.X_add_symbol = fde->end_address; exp.X_op_symbol = fde->start_address; /* Code length. */ emit_expr (&exp, 4); out_uleb128 (0); /* Augmentation size. */ for (; first; first = first->next) output_cfi_insn (first); frag_align (align, DW_CFA_nop, 0); symbol_set_value_now (end_address); }
static void output_cie (struct cie_entry *cie) { symbolS *after_size_address, *end_address; expressionS exp; struct cfi_insn_data *i; cie->start_address = symbol_temp_new_now (); after_size_address = symbol_temp_make (); end_address = symbol_temp_make (); exp.X_op = O_subtract; exp.X_add_symbol = end_address; exp.X_op_symbol = after_size_address; exp.X_add_number = 0; emit_expr (&exp, 4); /* Length. */ symbol_set_value_now (after_size_address); out_four (0); /* CIE id. */ out_one (DW_CIE_VERSION); /* Version. */ out_one ('z'); /* Augmentation. */ out_one ('R'); if (cie->signal_frame) out_one ('S'); out_one (0); out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH); /* Code alignment. */ out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT); /* Data alignment. */ if (DW_CIE_VERSION == 1) /* Return column. */ out_one (cie->return_column); else out_uleb128 (cie->return_column); out_uleb128 (1); /* Augmentation size. */ #if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4); #else out_one (DW_EH_PE_sdata4); #endif if (cie->first) for (i = cie->first; i != cie->last; i = i->next) output_cfi_insn (i); frag_align (2, DW_CFA_nop, 0); symbol_set_value_now (end_address); }
static void output_fde (struct fde_entry *fde, struct cie_entry *cie, struct cfi_insn_data *first, int align) { symbolS *after_size_address, *end_address; expressionS exp; offsetT augmentation_size; after_size_address = symbol_temp_make (); end_address = symbol_temp_make (); exp.X_op = O_subtract; exp.X_add_symbol = end_address; exp.X_op_symbol = after_size_address; exp.X_add_number = 0; emit_expr (&exp, 4); /* Length. */ symbol_set_value_now (after_size_address); exp.X_add_symbol = after_size_address; exp.X_op_symbol = cie->start_address; emit_expr (&exp, 4); /* CIE offset. */ #ifdef DIFF_EXPR_OK exp.X_add_symbol = fde->start_address; exp.X_op_symbol = symbol_temp_new_now (); emit_expr (&exp, 4); /* Code offset. */ #else exp.X_op = O_symbol; exp.X_add_symbol = fde->start_address; exp.X_op_symbol = NULL; #ifdef tc_cfi_emit_pcrel_expr tc_cfi_emit_pcrel_expr (&exp, 4); /* Code offset. */ #else emit_expr (&exp, 4); /* Code offset. */ #endif exp.X_op = O_subtract; #endif exp.X_add_symbol = fde->end_address; exp.X_op_symbol = fde->start_address; /* Code length. */ emit_expr (&exp, 4); augmentation_size = encoding_size (fde->lsda_encoding); out_uleb128 (augmentation_size); /* Augmentation size. */ if (fde->lsda_encoding != DW_EH_PE_omit) { exp = fde->lsda; if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel) { #ifdef DIFF_EXPR_OK exp.X_op = O_subtract; exp.X_op_symbol = symbol_temp_new_now (); emit_expr (&exp, augmentation_size); #elif defined (tc_cfi_emit_pcrel_expr) tc_cfi_emit_pcrel_expr (&exp, augmentation_size); #else abort (); #endif } else emit_expr (&exp, augmentation_size); } for (; first; first = first->next) output_cfi_insn (first); frag_align (align, DW_CFA_nop, 0); symbol_set_value_now (end_address); }
static void output_fde (struct fde_entry *fde, struct cie_entry *cie, bfd_boolean eh_frame, struct cfi_insn_data *first, int align) { symbolS *after_size_address, *end_address; expressionS exp; offsetT augmentation_size; enum dwarf2_format fmt = DWARF2_FORMAT (now_seg); int offset_size; int addr_size; after_size_address = symbol_temp_make (); end_address = symbol_temp_make (); exp.X_op = O_subtract; exp.X_add_symbol = end_address; exp.X_op_symbol = after_size_address; exp.X_add_number = 0; if (eh_frame || fmt == dwarf2_format_32bit) offset_size = 4; else { if (fmt == dwarf2_format_64bit) out_four (-1); offset_size = 8; } emit_expr (&exp, offset_size); /* Length. */ symbol_set_value_now (after_size_address); if (eh_frame) { exp.X_op = O_subtract; exp.X_add_symbol = after_size_address; exp.X_op_symbol = cie->start_address; exp.X_add_number = 0; emit_expr (&exp, offset_size); /* CIE offset. */ } else { TC_DWARF2_EMIT_OFFSET (cie->start_address, offset_size); } if (eh_frame) { exp.X_op = O_subtract; exp.X_add_number = 0; #if CFI_DIFF_EXPR_OK exp.X_add_symbol = fde->start_address; exp.X_op_symbol = symbol_temp_new_now (); emit_expr (&exp, DWARF2_FDE_RELOC_SIZE); /* Code offset. */ #else exp.X_op = O_symbol; exp.X_add_symbol = fde->start_address; #ifdef tc_cfi_emit_pcrel_expr tc_cfi_emit_pcrel_expr (&exp, DWARF2_FDE_RELOC_SIZE); /* Code offset. */ #else emit_expr (&exp, DWARF2_FDE_RELOC_SIZE); /* Code offset. */ #endif #endif addr_size = DWARF2_FDE_RELOC_SIZE; } else { exp.X_op = O_symbol; exp.X_add_symbol = fde->start_address; exp.X_add_number = 0; addr_size = DWARF2_ADDR_SIZE (stdoutput); emit_expr (&exp, addr_size); } exp.X_op = O_subtract; exp.X_add_symbol = fde->end_address; exp.X_op_symbol = fde->start_address; /* Code length. */ exp.X_add_number = 0; emit_expr (&exp, addr_size); augmentation_size = encoding_size (fde->lsda_encoding); if (eh_frame) out_uleb128 (augmentation_size); /* Augmentation size. */ if (fde->lsda_encoding != DW_EH_PE_omit) { exp = fde->lsda; if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel) { #if CFI_DIFF_LSDA_OK exp.X_op = O_subtract; exp.X_op_symbol = symbol_temp_new_now (); emit_expr (&exp, augmentation_size); #elif defined (tc_cfi_emit_pcrel_expr) tc_cfi_emit_pcrel_expr (&exp, augmentation_size); #else abort (); #endif } else emit_expr (&exp, augmentation_size); } for (; first; first = first->next) if (CUR_SEG (first) == CUR_SEG (fde)) output_cfi_insn (first); frag_align (align, DW_CFA_nop, 0); symbol_set_value_now (end_address); }
static void output_cie (struct cie_entry *cie, bfd_boolean eh_frame, int align) { symbolS *after_size_address, *end_address; expressionS exp; struct cfi_insn_data *i; offsetT augmentation_size; int enc; enum dwarf2_format fmt = DWARF2_FORMAT (now_seg); cie->start_address = symbol_temp_new_now (); after_size_address = symbol_temp_make (); end_address = symbol_temp_make (); exp.X_op = O_subtract; exp.X_add_symbol = end_address; exp.X_op_symbol = after_size_address; exp.X_add_number = 0; if (eh_frame || fmt == dwarf2_format_32bit) emit_expr (&exp, 4); /* Length. */ else { if (fmt == dwarf2_format_64bit) out_four (-1); emit_expr (&exp, 8); /* Length. */ } symbol_set_value_now (after_size_address); if (eh_frame) out_four (0); /* CIE id. */ else { out_four (-1); /* CIE id. */ if (fmt != dwarf2_format_32bit) out_four (-1); } out_one (DW_CIE_VERSION); /* Version. */ if (eh_frame) { out_one ('z'); /* Augmentation. */ if (cie->per_encoding != DW_EH_PE_omit) out_one ('P'); if (cie->lsda_encoding != DW_EH_PE_omit) out_one ('L'); out_one ('R'); } if (cie->signal_frame) out_one ('S'); out_one (0); out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH); /* Code alignment. */ out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT); /* Data alignment. */ if (DW_CIE_VERSION == 1) /* Return column. */ out_one (cie->return_column); else out_uleb128 (cie->return_column); if (eh_frame) { augmentation_size = 1 + (cie->lsda_encoding != DW_EH_PE_omit); if (cie->per_encoding != DW_EH_PE_omit) augmentation_size += 1 + encoding_size (cie->per_encoding); out_uleb128 (augmentation_size); /* Augmentation size. */ if (cie->per_encoding != DW_EH_PE_omit) { offsetT size = encoding_size (cie->per_encoding); out_one (cie->per_encoding); exp = cie->personality; if ((cie->per_encoding & 0x70) == DW_EH_PE_pcrel) { #if CFI_DIFF_EXPR_OK exp.X_op = O_subtract; exp.X_op_symbol = symbol_temp_new_now (); emit_expr (&exp, size); #elif defined (tc_cfi_emit_pcrel_expr) tc_cfi_emit_pcrel_expr (&exp, size); #else abort (); #endif } else emit_expr (&exp, size); } if (cie->lsda_encoding != DW_EH_PE_omit) out_one (cie->lsda_encoding); } switch (DWARF2_FDE_RELOC_SIZE) { case 2: enc = DW_EH_PE_sdata2; break; case 4: enc = DW_EH_PE_sdata4; break; case 8: enc = DW_EH_PE_sdata8; break; default: abort (); } #if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr enc |= DW_EH_PE_pcrel; #endif if (eh_frame) out_one (enc); if (cie->first) { for (i = cie->first; i != cie->last; i = i->next) { if (CUR_SEG (i) != CUR_SEG (cie)) continue; output_cfi_insn (i); } } frag_align (align, DW_CFA_nop, 0); symbol_set_value_now (end_address); }