This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix .cfi_* directive skip over >= 64KB (PR gas/10255)


Hi!

When .cfi_* directives need to skip from one fragment to another one and
that skip in the end turns to be >= 64KB, the generated .eh_frame section
is incorrect.  The problem is that we add the needed 1 byte fragment
before rs_cfa fragment, but don't initialize it, so it often remains
at DW_CFA_nop (or could be any other opcode).  Later on when
eh_frame_convert_frag is called, if the skip is small, the previous
fragment's byte is changed into DW_CFA_advance_loc | distance,
DW_CFA_advance_loc1 or DW_CFA_advance_loc2.  But if it is >= 65536,
ehopt.c assumes (IMHO correctly) that the byte before it is
DW_CFA_advance_loc4 and doesn't change it, so we end up with a random opcode
(usually DW_CFA_nop) followed by the 4 byte skip value (which is
interpreted as random, often invalid, opcodes).

Ok for trunk?

2009-06-09  Jakub Jelinek  <jakub@redhat.com>

	PR gas/10255
	* dw2gencfi.c (output_cfi_insn): Initialize fragment before rs_cfa
	to DW_CFA_advance_loc4.

	* gas/cfi/cfi-common-7.d: New test.
	* gas/cfi/cfi-common-7.s: New.
	* gas/cfi/cfi.exp: Add cfi-common-7 test.

--- gas/dw2gencfi.c.jj	2009-01-27 17:50:43.000000000 +0100
+++ gas/dw2gencfi.c	2009-06-09 13:51:19.000000000 +0200
@@ -1,5 +1,6 @@
 /* dw2gencfi.c - Support for generating Dwarf2 CFI information.
-   Copyright 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed by Michal Ludvig <mludvig@suse.cz>
 
    This file is part of GAS, the GNU Assembler.
@@ -1001,7 +1002,7 @@ output_cfi_insn (struct cfi_insn_data *i
 	       is already allocated to the frag.  This comes from the way
 	       that it scans the .eh_frame section looking first for the
 	       .byte DW_CFA_advance_loc4.  */
-	    frag_more (1);
+	    *frag_more (1) = DW_CFA_advance_loc4;
 
 	    frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
 		      make_expr_symbol (&exp), frag_now_fix () - 1,
--- gas/testsuite/gas/cfi/cfi.exp.jj	2008-09-25 20:39:42.000000000 +0200
+++ gas/testsuite/gas/cfi/cfi.exp	2009-06-09 14:07:08.000000000 +0200
@@ -89,6 +89,7 @@ if { ![istarget "hppa64*-*"] } then {
   run_dump_test "cfi-common-3"
   run_dump_test "cfi-common-4"
   run_dump_test "cfi-common-5"
+  run_dump_test "cfi-common-7"
 }
 
 # MIPS doesn't support PC relative cfi directives.
--- gas/testsuite/gas/cfi/cfi-common-7.d.jj	2009-06-09 13:58:25.000000000 +0200
+++ gas/testsuite/gas/cfi/cfi-common-7.d	2009-06-09 14:04:33.000000000 +0200
@@ -0,0 +1,22 @@
+#readelf: -wf
+#name: CFI common 7
+Contents of the .eh_frame section:
+
+00000000 00000010 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: .*
+  Data alignment factor: .*
+  Return address column: .*
+  Augmentation data:     [01]b
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000014 000000(1c|20) 00000018 FDE cie=00000000 pc=.*
+  DW_CFA_advance_loc: 16 to .*
+  DW_CFA_def_cfa: r0( \([er]ax\)|) ofs 16
+  DW_CFA_advance_loc4: 75031 to .*
+  DW_CFA_def_cfa: r0( \([er]ax\)|) ofs 64
+#...
--- gas/testsuite/gas/cfi/cfi-common-7.s.jj	2009-06-09 13:57:19.000000000 +0200
+++ gas/testsuite/gas/cfi/cfi-common-7.s	2009-06-09 13:59:34.000000000 +0200
@@ -0,0 +1,6 @@
+	.cfi_startproc simple
+	.skip 16
+	.cfi_def_cfa 0, 16
+	.skip 75031
+	.cfi_def_cfa 0, 64
+	.cfi_endproc

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]