http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47324
--- Comment #33 from Iain Sandoe <iains at gcc dot gnu.org> 2011-02-10 14:39:46 UTC --- in addition to Mike's fix, the dw_loc_descr_ref reg numbers need to be adjusted in the loc lists, below is a hack which works - I don't know the code well enough to know if the dw_loc_opc should just be written to the translated version in the first place. ===== Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c (revision 170000) +++ gcc/dwarf2out.c (working copy) @@ -474,7 +474,7 @@ static bool clobbers_queued_reg_save (const_rtx); static void dwarf2out_frame_debug_expr (rtx, const char *); /* Support for complex CFA locations. */ -static void output_cfa_loc (dw_cfi_ref); +static void output_cfa_loc (dw_cfi_ref, int); static void output_cfa_loc_raw (dw_cfi_ref); static void get_cfa_from_loc_descr (dw_cfa_location *, struct dw_loc_descr_struct *); @@ -3317,7 +3317,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int fo case DW_CFA_def_cfa_expression: case DW_CFA_expression: - output_cfa_loc (cfi); + output_cfa_loc (cfi, for_eh); break; case DW_CFA_GNU_negative_offset_extended: @@ -5291,13 +5291,21 @@ output_loc_operands (dw_loc_descr_ref loc) /* Output a sequence of location operations. */ static void -output_loc_sequence (dw_loc_descr_ref loc) +output_loc_sequence (dw_loc_descr_ref loc, int for_eh) { for (; loc != NULL; loc = loc->dw_loc_next) { /* Output the opcode. */ - dw2_asm_output_data (1, loc->dw_loc_opc, - "%s", dwarf_stack_op_name (loc->dw_loc_opc)); + if (for_eh && loc->dw_loc_opc >= DW_OP_breg0 && loc->dw_loc_opc <= DW_OP_breg31) + { + unsigned r = (loc->dw_loc_opc - DW_OP_breg0); + r = DWARF2_FRAME_REG_OUT (r, for_eh) ; + dw2_asm_output_data (1, (r+DW_OP_breg0), + "%s", dwarf_stack_op_name (r+DW_OP_breg0)); + } + else + dw2_asm_output_data (1, loc->dw_loc_opc, + "%s", dwarf_stack_op_name (loc->dw_loc_opc)); /* Output the operand(s) (if any). */ output_loc_operands (loc); @@ -5451,14 +5459,16 @@ output_loc_sequence_raw (dw_loc_descr_ref loc) description based on a cfi entry with a complex address. */ static void -output_cfa_loc (dw_cfi_ref cfi) +output_cfa_loc (dw_cfi_ref cfi, int for_eh) { dw_loc_descr_ref loc; unsigned long size; if (cfi->dw_cfi_opc == DW_CFA_expression) { - dw2_asm_output_data (1, cfi->dw_cfi_oprnd1.dw_cfi_reg_num, NULL); + unsigned long r = + DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh); + dw2_asm_output_data (1, r, NULL); loc = cfi->dw_cfi_oprnd2.dw_cfi_loc; } else @@ -5469,7 +5479,7 @@ static void dw2_asm_output_data_uleb128 (size, NULL); /* Now output the operations themselves. */ - output_loc_sequence (loc); + output_loc_sequence (loc, for_eh); } /* Similar, but used for .cfi_escape. */ @@ -11075,7 +11085,7 @@ output_loc_list (dw_loc_list_ref list_head) gcc_assert (size <= 0xffff); dw2_asm_output_data (2, size, "%s", "Location expression size"); - output_loc_sequence (curr->expr); + output_loc_sequence (curr->expr, 0); } dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, @@ -11153,7 +11163,7 @@ output_die (dw_die_ref die) else dw2_asm_output_data (constant_size (size), size, "%s", name); - output_loc_sequence (AT_loc (a)); + output_loc_sequence (AT_loc (a), 0); break; case dw_val_class_const: